主要理解select函数,涉及到一些 宏和 数组定义
分为两端
Server端:
// soctet_server.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <string.h> #include <stdlib.h> #include <Winsock2.h> #pragma comment(lib,"Ws2_32.lib") SOCKET gClientSockAddr[FD_SETSIZE]={0}; DWORD gClientSockNum = 0; HANDLE ghMutex = NULL; DWORD WINAPI RecvSendThead(LPVOID lpvoid); DWORD WINAPI RecvSendThead(LPVOID lpvoid) { timeval timeout = {3,0}; while(TRUE) { DWORD ClientSockNum = gClientSockNum; if(ClientSockNum) { FD_SET readset; FD_ZERO (&readset); for(DWORD i=0;i<ClientSockNum;i++) { FD_SET(gClientSockAddr[i],&readset); } int ReadableNum = select(0,&readset,NULL,NULL,&timeout); if(ReadableNum == 0) { continue; }else{ for(DWORD k = 0;k<ClientSockNum;k++) { if(FD_ISSET(gClientSockAddr[k],&readset)) { char buf[MAX_PATH] = {0}; int recvlen = recv(gClientSockAddr[k],buf,MAX_PATH,0); //if(strcmp(buf,"quit") == 0) if(strcmp(buf,"quit") == 0) { //断开 shutdown(gClientSockAddr[k],SD_SEND); closesocket(gClientSockAddr[k]); WaitForSingleObject(ghMutex,INFINITE); gClientSockAddr[k] = gClientSockAddr[gClientSockNum-1]; gClientSockAddr[gClientSockNum - 1] = NULL; gClientSockNum-=1; ReleaseMutex(ghMutex); } if(recvlen ==0 || recvlen == -1) { //断开 shutdown(gClientSockAddr[k],SD_SEND); closesocket(gClientSockAddr[k]); WaitForSingleObject(ghMutex,INFINITE); gClientSockAddr[k] = gClientSockAddr[gClientSockNum-1]; gClientSockAddr[gClientSockNum - 1] = NULL; gClientSockNum-=1; ReleaseMutex(ghMutex); }else{ printf("Client Message: %s\n",buf); send(gClientSockAddr[k],buf,strlen(buf)+1,0); memset(buf,0,MAX_PATH); } } } } } } return 0; } int main(int argc, char* argv[]) { //0:初始化 WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { /* Tell the user that we could not find a usable */ /* WinSock DLL. */ return 0; } //1 create socket SOCKET hSerSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); //2 bind struct sockaddr_in SerAddr={0}; SerAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); SerAddr.sin_family = AF_INET; SerAddr.sin_port = htons(2018); bind(hSerSocket,(sockaddr*)&SerAddr,sizeof(SerAddr)); //3 listen listen(hSerSocket,5); //4 accept ghMutex = CreateMutex(NULL,FALSE,NULL); HANDLE hThread = CreateThread(NULL,0,RecvSendThead,NULL,0,NULL); CloseHandle(hThread); while(TRUE) { struct sockaddr ClientAddr={0}; int ClientAddrLen = sizeof(sockaddr); SOCKET hClientSocket = accept(hSerSocket,(sockaddr*)&ClientAddr,&ClientAddrLen); WaitForSingleObject(ghMutex,INFINITE); gClientSockAddr[gClientSockNum++] = hClientSocket; printf("第 %d 个客户进来\n",gClientSockNum); ReleaseMutex(ghMutex); } //5 send recv closesocket(hSerSocket); WSACleanup(); return 0; }
Client客户端
// socket_client.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <Winsock2.h> #pragma comment(lib,"Ws2_32.lib") int main(int argc, char* argv[]) { /* 创建套接字 绑定套接字 连接服务器 收发数据 断开连接(主动) 关闭套接字 */ //0:初始化 WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { /* Tell the user that we could not find a usable */ /* WinSock DLL. */ return 0; } //1 create socket SOCKET hCliSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); //2 connet struct sockaddr_in SerAddr={0}; SerAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); SerAddr.sin_family = AF_INET; SerAddr.sin_port = htons(2018); connect(hCliSocket,(sockaddr*)&SerAddr,sizeof(SerAddr)); //3 send/recv char sendBuf[100]={0}; while(TRUE) { scanf("%s",&sendBuf); if(strcmp(sendBuf,"quit")==0) { break; } send(hCliSocket,sendBuf,strlen(sendBuf)+1,0); char recvBuf[100]={0}; recv(hCliSocket,recvBuf,100,0); printf("client: %s\n",recvBuf); } shutdown(hCliSocket,SD_RECEIVE); closesocket(hCliSocket); return 0; }
0则评论给“Select 多线程通信,模型实例”