造了线程用select IO模型:
#include <winsock.h> #include <stdio.h> #define PORT 5010 #define MSGSIZE 1024 #pragma comment(lib, "ws2_32.lib") int g_iTotalConn = 0; SOCKET g_CliSocketArr[FD_SETSIZE]; DWORD WINAPI WorkerThread(LPVOID lpParameter); int main() { WSADATA wsaData; SOCKET sListen, sClient; SOCKADDR_IN local, client; DWORD dwThreadId; // Initialize Windows socket library WSAStartup(0x0202, &wsaData); // Create listening socket sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // Bind local.sin_addr.S_un.S_addr = htonl(INADDR_ANY); local.sin_family = AF_INET; local.sin_port = htons(PORT); bind(sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN)); // Listen listen(sListen, 3); // Create worker thread CreateThread(NULL, 0, WorkerThread, NULL, 0, &dwThreadId); while (TRUE) { // Accept a connection int iaddrSize = sizeof(client); sClient = accept(sListen, (sockaddr*)&client, &iaddrSize); printf("Accepted client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port)); // Add socket to g_CliSocketArr g_CliSocketArr[g_iTotalConn++] = sClient; } return 0; } DWORD WINAPI WorkerThread(LPVOID lpParam) { int i = 0; fd_set fdread; int ret = 0; struct timeval tv = {1, 0}; char szMessage[MSGSIZE]; while (TRUE) { FD_ZERO(&fdread); for (i = 0; i < g_iTotalConn; i++) { FD_SET(g_CliSocketArr[i], &fdread);//把所有的socket都塞到fd_set中 } // We only care read event ret = select(0, &fdread, NULL, NULL, &tv);//检测是否有数据可读 if (ret == 0) { // Time expired continue; } for (i = 0; i < g_iTotalConn; i++) { if (FD_ISSET(g_CliSocketArr[i], &fdread))//对有数据可读的那个套接字 进行处理 { // A read event happened on g_CliSocketArr ret = recv(g_CliSocketArr[i], szMessage, MSGSIZE, 0); if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET)) {//处理发生错误的时候 // Client socket closed printf("Client socket %d closed.\n", g_CliSocketArr); closesocket(g_CliSocketArr[i]); if (i < g_iTotalConn - 1) { g_CliSocketArr[i--] = g_CliSocketArr[--g_iTotalConn]; } } else {//正常的情况 // We received a message from client send(g_CliSocketArr[i], szMessage, ret, 0); } } } }//while return 0; }
客户端:
#include<WinSock2.h> #include <iostream> #include <string> using namespace std; #pragma comment(lib, "WS2_32") short gPort = 5010; const int MaxLine = 1024; void StrClient(SOCKET &aSockfd) { string lStr; while (getline(cin, lStr) != NULL) { send(aSockfd,lStr.c_str(),lStr.size(),0); char lSendline[MaxLine]; int lReadSize = 0; if ( (lReadSize = recv(aSockfd,lSendline,MaxLine,0) ) == 0 ) { cerr << "sever terminated prematurely\n"; return ; } string lRecvStr(lSendline,lReadSize); cout << lRecvStr << endl; } } int main() { int lRet = 0; WSADATA lWsaData; if ((lRet = WSAStartup(MAKEWORD(2,2), &lWsaData)) != 0) { cout << "Error " << lRet << endl; return 0; } SOCKADDR_IN lAddr; lAddr.sin_family = AF_INET; lAddr.sin_port = htons(gPort); int lNum = 0; int lReadTime = 0; SOCKET lSocket = socket(AF_INET, SOCK_STREAM, 0); if (INVALID_SOCKET == lSocket) { cout << "INVALID_SOCKET" << endl; return 0; } lAddr.sin_addr.s_addr = inet_addr("192.168.1.102"); if (connect(lSocket,(sockaddr*)(&lAddr),sizeof(lAddr)) < 0 ) { cout << "connect error" << endl; return 0; } StrClient(lSocket); return 0; }