Winsock编程原理——面向连接
Windows Sockets使用套接字进行编程,套接字编程是面向客户端/服务器模型而设计的,因此系统中需要客户端和服务器两个不同类型的进程,根据连接类型的不同,对于面向连接的TCP服务和无连接的UDP服务,服务器分别采取不同的处理操作来对客户提供服务。
面向连接
服务器
socket() -> bind() -> listen() -> accept() -> recv()/send()
-> closesocket();
创建套接字,绑定IP和端口,侦听,接收连接,收发消息,关闭连接
客户端
socket() -> connet() -> send()/recv() -> closesocket();
创建套接字,连接服务器,发收消息,关闭连接
1 /* 2 服务器端代码 3 */ 4 5 #include<Winsock2.h> 6 #include<stdio.h> 7 #include<stdlib.h> 8 #pragma comment(lib,"ws2_32.lib") 9 #define PORT 5000 10 11 void main() 12 { 13 int port = PORT; //端口 14 WSADATA wsaData; //存储系统传回的关于Winsock的资料 15 SOCKET sListen, sAccept; //套接字 16 int iLen; //客户地址长度 17 int iSend; //发送数据长度 18 char buf[] = "Hello, How are you!"; //需要发送的信息 19 struct sockaddr_in serv, cliet; //服务器、客户的地址 20 21 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) //函数WSAStartup用以打开Winsock 22 { 23 printf("Winsock load failed\n"); 24 return; 25 } 26 27 sListen = socket(AF_INET, SOCK_STREAM, 0); //创建套接字,TCP协议 28 if (sListen == INVALID_SOCKET) //socket调用成功返回套接字对象,失败返回INVALID_SOCKET 29 { 30 printf("socket failed:%d\n", WSAGetLastError()); 31 return; 32 } 33 34 serv.sin_family = AF_INET; //网络中标识不同设备使用的地址类型,对于IP地址,类型是AF_INET 35 serv.sin_port = htons(port); //socket对应的端口号 36 serv.sin_addr.s_addr = htonl(INADDR_ANY); //封装了IP地址 37 if (bind(sListen, (LPSOCKADDR)&serv, sizeof(serv)) == SOCKET_ERROR) //绑定套接字 38 { 39 printf("bind() failed:%d\n", WSAGetLastError()); 40 return; 41 } 42 43 if (listen(sListen, 5) == SOCKET_ERROR) //监听 44 { 45 printf("listen() failed:%d\n", WSAGetLastError()); 46 return; 47 } 48 49 iLen = sizeof(cliet); //初始化客户地址长度 50 51 while (1) //进入循环,等待客户连接请求 52 { 53 sAccept = accept(sListen, (struct sockaddr*)&cliet, &iLen); //客户端的套接字 54 if (sAccept == INVALID_SOCKET) //接受连接请求失败 55 { 56 printf("accept() failed:%d\n", WSAGetLastError()); 57 break; 58 } 59 //输出客户端IP、端口 60 printf("accept() client IP:[%s], port:[%d]\n", inet_ntoa(cliet.sin_addr), ntohs(cliet.sin_port)); 61 62 //给连接的客户发送消息 63 iSend = send(sAccept, buf, sizeof(buf), 0); 64 if (iSend == SOCKET_ERROR) 65 { 66 printf("send() failed:%d\n", WSAGetLastError()); 67 break; 68 } 69 else if (iSend == 0) 70 break; 71 else 72 printf("send() byte:%d\n", send); 73 74 closesocket(sListen); //关闭套接字 75 closesocket(sAccept); //关闭套接字 76 WSACleanup(); //关闭Winsock 77 } 78 while (1); 79 }
1 /* 2 客户端程序 3 */ 4 #include<WinSock2.h> 5 #include<stdio.h> 6 #pragma comment(lib,"ws2_32.lib") 7 #define PORT 5000 8 #define BUFFER 1024 9 10 void main(int argc,char *argv[]) 11 { 12 WSADATA wsaData; 13 SOCKET client; 14 int port = PORT; 15 int iLen; //从服务器接收的数据长度 16 char buf[BUFFER]; //接收数据的缓冲 17 struct sockaddr_in serv; //服务器端地址 18 memset(buf, 0, sizeof(buf)); //接受数据缓冲区初始化 19 20 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) //函数WSAStartup用以打开Winsock 21 { 22 printf("Winsock load failed\n"); 23 return; 24 } 25 26 serv.sin_family = AF_INET; //需要连接服务器地址信息,AF_INET表示IP协议 27 serv.sin_port = htons(port); //端口 28 // serv.sin_addr.s_addr = inet_addr(argv[1]); //IP地址,转为二进制表示的字节IP地址,argv表示cmd下输入的参数 29 serv.sin_addr.s_addr = inet_addr("10.100.211.224"); 30 client = socket(AF_INET, SOCK_STREAM, 0); //客户端套接字,流套接字表示使用TCP协议 31 if (client == INVALID_SOCKET) //创建套接字失败 32 { 33 printf("socket() failed:%d\n", WSAGetLastError()); 34 return; 35 } 36 37 //连接服务器 38 if (connect(client, (struct sockaddr*)&serv, sizeof(serv)) == INVALID_SOCKET) 39 { 40 printf("connet() failed:%d\n", WSAGetLastError); 41 return; 42 } 43 else 44 { 45 iLen = recv(client, buf, sizeof(buf), 0); //从服务器接收数据 46 if (iLen = 0) 47 return; 48 else if (iLen == SOCKET_ERROR) 49 { 50 printf("recv() failed:%d\n", WSAGetLastError()); 51 return; 52 } 53 printf("recv() data from server:%s\n", buf); 54 } 55 56 closesocket(client); //关闭套接字 57 WSACleanup; //关闭Winsock 58 59 // system("pause"); //程序暂停 60 printf("press any key to continue"); //让程序等待 61 while (1); 62 }