【Windows网络编程】Select网络模型

来源:互联网 发布:linux增加分辨率 编辑:程序博客网 时间:2024/04/29 12:49
#include <WinSock2.h>#include <stdio.h>#define PORT 6000#pragma comment (lib, "Ws2_32.lib")fd_set g_fdClientSock;         //file discriotin set集合int clientNum = 0;BOOL WinSockInit(){WSADATA data = { 0 };if (WSAStartup(MAKEWORD(2, 2), &data))return FALSE;if (LOBYTE(data.wVersion) != 2 || HIBYTE(data.wVersion) != 2){WSACleanup();return FALSE;}return TRUE;}DWORD WINAPI ListenThreadProc(LPARAM lparam){fd_set fdRead;FD_ZERO(&fdRead);int nRet = 0;char* recvBuffer = (char*)malloc(sizeof(char)* 1024);if (NULL == recvBuffer){return -1;}memset(recvBuffer, 0, sizeof(char)* 1024);while (true){fdRead = g_fdClientSock;timeval tv;tv.tv_sec = 1;tv.tv_usec = 0;//select操作会阻塞的检查整个FD_SET数组里面的所有soket是否有信号来了//解决了标准TCP n个客户就要n+1个线程的问题//线程时间片没有充分利用nRet = select(0, &fdRead, NULL, NULL, &tv);      //sleep将线程休眠操作if (nRet != SOCKET_ERROR){//找到数组内哪个sokect有信号for (int i = 0; i < g_fdClientSock.fd_count; i++){//遍历有哪些sokect有数据信号到达if (FD_ISSET(g_fdClientSock.fd_array[i], &fdRead)){//与客户通信memset(recvBuffer, 0, sizeof(char)* 1024);nRet=(recv(g_fdClientSock.fd_array[i], recvBuffer, 1024, 0));if (nRet == SOCKET_ERROR){closesocket(g_fdClientSock.fd_array[i]);clientNum--;FD_CLR(g_fdClientSock.fd_array[i], &g_fdClientSock);}else if (nRet==0){closesocket(g_fdClientSock.fd_array[i]);clientNum--;FD_CLR(g_fdClientSock.fd_array[i], &g_fdClientSock);}else{//todo:后续处理printf("Recv msg:%s\n", recvBuffer);send(g_fdClientSock.fd_array[i], recvBuffer, strlen(recvBuffer), 0);}}}}}if (recvBuffer != NULL)free(recvBuffer);return 0;}int main(){WinSockInit();SOCKET ListenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);struct sockaddr_in server;server.sin_family = AF_INET;server.sin_addr.s_addr = htonl(INADDR_ANY);server.sin_port = htons(PORT);int ret = bind(ListenSock, (sockaddr*)&server, sizeof(server));ret = listen(ListenSock, 4);sockaddr_in clientAddr;int nameLen = sizeof(clientAddr);//先把服务器创建起来CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ListenThreadProc, NULL, NULL, NULL);//主线程里面开始进行Accept操作while (clientNum < FD_SETSIZE)  //FD_SETSIZE=64{//当有一个客户端进行连接时,主线程的Accept会进行返回SOCKET clientSock = accept(ListenSock, (sockaddr*)&clientAddr, &nameLen);FD_SET(clientSock, &g_fdClientSock);clientNum++;}closesocket(ListenSock);WSACleanup();return 0;}

原创粉丝点击