网站 前台后台,东莞seo关键词,电子商务网站开发主要实现功能,wordpress acf使用编译环境#xff1a;VS Code  gcc#xff0c;环境搭建可以参考这里。本系列文章参考 尹圣雨 著的《TCP/IP网络编程》。 所有学习都要在开始前认识到其必要性#xff01;这是我经常挂在嘴边的一句话。从语言的基本语法到系统函数#xff0c;若无法回答“这到底有何必要…编译环境VS Code  gcc环境搭建可以参考这里。本系列文章参考 尹圣雨 著的《TCP/IP网络编程》。 所有学习都要在开始前认识到其必要性这是我经常挂在嘴边的一句话。从语言的基本语法到系统函数若无法回答“这到底有何必要”学习过程将变得枯燥无味而且很容易遗忘。 — 尹圣雨 SOCKET 编程头文件和库 
使用 Windows Socket 编程需要 winsock2.h 头文件和 ws2_32.lib 库。 对于 gcc 编译器加载 ws2_32.lib 库需要在编译参数中添加参数-lwsock32 。否则 gcc 会因为没有找到库而报错编译的时候出现 undefined reference to __imp_WSAStartup’。 具体添加方法为 
在工程文件夹下打开 .vscode 文件夹打开 tasks.json 文件在 args 字段中添加新的参数 -lwsock32 如下图所示。  
Windows SOCKET 初始化 
以下是 Windows SOCKET 编程固定格式。 
#include winsock2.hint main(int argc, char *argv[])
{WSADATA wsaData;// ...if(WSAStartup(MAKEWORD(2, 2), wsaData) ! 0){// ...exit(1);}// ...WSACleanup();return 0;
}首先必须调用 WSAStartup 函数设置程序中用到的 Windows SOCKET 版本并初始化相应版本的库。 WSAStartup 函数原型为 
/*成功返回 0 失败返回非零错误码*/
int  WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);Windows SOCKET 存在多个版本参数 wVersionRequested 指明使用哪个版本。版本占用 2 字节高 8 位为副版本低 8 位为主版本比如 V1.2 版本则传递 0x0201。一般会使用 MAKEWORD 宏来构建版本信息 
WORD ver  MAKEWORD(1, 2);			// V1.2 版本 ver  0x0201第二个参数 lpWSAData 用于保存库信息。 
其次当程序结束之前需要调用 WSACleanup 注销 SOCKET 库。 
Windows SOCKET 相关函数 
socket 函数 
/*成功返回 SOCKET 句柄失败返回 INVALID_SOCKET*/
SOCKET socket(int af,int type,int protocol);af 指定 SOCKET 使用的 协议族 一个 协议族 下面会有多种 协议 比如 iPv4 协议族就有 TCP 协议、UDP 协议等等一个 协议族 下面也有多种数据传输方式。 常见协议族有IPv4协议族PF_INET、IPv6协议族PF_INET6、底层 SOCKET 的协议族PF_PACKET。type指定 SOCKET 的 数据传输方式。 常见的数据传输方式有面向连接的SOCK_STREAM、面向消息的SOCK_DGRAM 面向连接的 SOCKET 可靠的、按序传递的、基于字节的面向连接的数据传输方式 面向消息的 SOCKET不可靠的、不按序传递的、以数据的高速传输为目的 protocol指定 SOCKET 使用的 协议该协议必须是协议族支持的协议之一。 常见的协议类型有TCP 协议IPPROTO_TCP、UDP 协议IP_PROTO_UDP 
bind 函数 
/*成功返回 0 失败返回 SOCKET_ERROR*/
int bind(SOCKET s,const struct sockaddr *name,int namelen);listen 函数 
/*成功返回 0 失败返回 SOCKET_ERROR
* backlog连接请求队列的长度表示允许最多多少个连接请求进入队列
*/
int listen(SOCKET s,int backlog);accept 函数 调用 accept 函数时若等待队列为空则 accept 函数不会返回直到队列中出现新的客户端连接。 
/*成功返回 SOCKET 句柄失败返回 INVALID_SOCKET
* addr保存客户端地址信息
*/
SOCKET accept(SOCKET s,struct sockaddr *addr,int *addrlen);connect 函数 客户端调用 connect 函数后发生以下情况之一才会返回 a. 服务器端接收连接请求 b. 发生断网等异常情况而中断连接请求 
/*成功返回 0 失败返回 SOCKET_ERROR */
int connect(SOCKET s,const struct sockaddr *name,int namelen);closesocket 函数 
/*成功返回 0 失败返回 SOCKET_ERROR*/
int closesocket(SOCKET s);Windows 的 I/O 函数 
Windows 严格区分文件 I/O 函数和 SOCKET I/O函数而Linux只有文件 I/O 函数。 
send 函数 
/*成功返回传输的字节数失败返回 SOCKET_ERROR*/
int send(SOCKET s,const char *buf,int len,int flags);recv 函数 
/*成功返回接收的字节数收到 EOF 时为 0 失败返回 SOCKET_ERROR*/
int WSAAPI recv(SOCKET s,char *buf,int len,int flags);基于 Windoes 的服务器和客户端测试代码 
服务器端 
#include stdio.h
#include stdlib.h
#include winsock2.hvoid ErrorHandler(char *message);int main(int argc, char *argv[])
{WSADATA wsaData;SOCKET hServSock, hClntSock;SOCKADDR_IN servAddr, clntAddr;int szClntAddr;char message[]  Hello, world!;if(argc ! 2){printf (Usage: %s port\n, argv[0]);exit(1);}if(WSAStartup(MAKEWORD(2,2), wsaData) ! 0){ErrorHandler(WSAStartup failed);}hServSock  socket(PF_INET, SOCK_STREAM, 0);if(hServSock  INVALID_SOCKET)ErrorHandler(socket error);memset(servAddr, 0, sizeof(servAddr));servAddr.sin_family  AF_INET;servAddr.sin_addr.s_addr  htonl(INADDR_ANY);servAddr.sin_port  htons(atoi(argv[1]));if(bind(hServSock, (SOCKADDR *)servAddr, sizeof(servAddr))  SOCKET_ERROR){ErrorHandler(bind socket error);}if(listen(hServSock, 5)  SOCKET_ERROR)ErrorHandler(listen socket error);szClntAddr  sizeof(clntAddr);hClntSock  accept(hServSock, (SOCKADDR *)clntAddr, szClntAddr);if(hClntSock  INVALID_SOCKET)ErrorHandler(accept error);send(hClntSock, message, sizeof(message), 0);closesocket(hClntSock);closesocket(hServSock);WSACleanup();return 0;
}void ErrorHandler(char *message)
{fputs(message, stderr);fputc(\n, stderr);exit(1);
}编译菜单 Terminal  Run Build Task 或者快捷键 CtrlShiftB 。 运行在终端键入 .\hello_server_win.exe 1234 
客户端 
#include stdio.h
#include stdlib.h
#include winsock2.hvoid ErrorHandler(char *message);int main(int argc, char *argv[])
{WSADATA wsaData;SOCKET hClntSock;SOCKADDR_IN servAddr;char message[30];int strLen;if(argc ! 3){printf (Usage: %s IP port\n, argv[0]);exit(1);}if(WSAStartup(MAKEWORD(2,2), wsaData) ! 0)ErrorHandler(WSAStartup failed);hClntSock  socket(PF_INET, SOCK_STREAM, 0);if(hClntSock  INVALID_SOCKET)ErrorHandler(socket error);memset(servAddr, 0, sizeof(servAddr));servAddr.sin_family  AF_INET;servAddr.sin_addr.s_addr  inet_addr(argv[1]);servAddr.sin_port  htons(atoi(argv[2]));if(connect(hClntSock, (SOCKADDR *)servAddr, sizeof(servAddr))  SOCKET_ERROR)ErrorHandler(connect socket error);strLen  recv(hClntSock, message, sizeof(message)-1, 0);if(strLen  EOF)ErrorHandler(read() error!);printf(Message from server: %s \n, message);closesocket(hClntSock);WSACleanup();return 0;
}void ErrorHandler(char *message)
{fputs(message, stderr);fputc(\n, stderr);exit(1);
}编译菜单 Terminal  Run Build Task 或者快捷键 CtrlShiftB 。 运行在终端键入 .\hello_client_win.exe 127.0.0.1 1234