在非阻塞的accetp成功后就创建一个线程来处理新的客户端,并将客户端socket和地址作为参数传给线程函数.
在非阻塞的代码中修改一下即可
示例代码:
/* 主线程进行accpet,每次accpet成功后就生成一个线程处理这个连接过来的 客户端 */ #define WIN32_LEAN_AND_MEAN #include<iostream> #include<string> #include<winsock2.h> using namespace std; #pragma comment(lib,"ws2_32.lib") DWORD WINAPI handleThreadProc(LPVOID param[]) { char recv_buffer[1024]; char send_buffer[1024]; int error_code; //存储WSAGetLastError()的返回值 int len = sizeof(SOCKADDR); SOCKET client_socket = (SOCKET)param[0]; SOCKADDR_IN* client_addr=(SOCKADDR_IN*)param[1]; //解决非阻塞的recv和send cout << "connect by " << inet_ntoa(client_addr->sin_addr) << ntohs(client_addr->sin_port) << endl; while (1) { memset(recv_buffer, '\0', 1024); //对于该函数,由于是非阻塞模式,没有数据不会阻塞,错误处理和上面类似 if (recv(client_socket, recv_buffer, 1024, 0) == SOCKET_ERROR) { error_code = WSAGetLastError(); if (error_code == WSAEWOULDBLOCK) { Sleep(100); continue; } else { cout << "recv error code is " << error_code << endl; closesocket(client_socket); WSACleanup(); return -4; } } if (strcmp(recv_buffer, "quit") == 0) { cout << "客户端退出" << endl; closesocket(client_socket); return 1; } else { while (1) { cout << "recvice from :" << inet_ntoa(client_addr->sin_addr) << ntohs(client_addr->sin_port)<<"\t" << recv_buffer << endl; cin >> send_buffer; if (send(client_socket, send_buffer, strlen(send_buffer) + 1, 0) == SOCKET_ERROR) { error_code = WSAGetLastError(); if (error_code == WSAEWOULDBLOCK) { Sleep(200); continue; } else { cout << "send error code is " << error_code << endl; closesocket(client_socket); return -5; } } break; } } } return 1; } int main() { WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData)) { cout << "版本错误, error code is " << WSAGetLastError() << endl; return 1; } ULONG noblock = 1; //非阻塞参数 SOCKET server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); SOCKET client_socket; SOCKADDR_IN bind_addr; SOCKADDR_IN client_addr; LPVOID params[2]; int error_code; //存储WSAGetLastError()的返回值 int len = sizeof(SOCKADDR); //设置非阻塞socket if (!ioctlsocket(server_socket, FIONBIO, &noblock)) { cout << "设置非阻塞模式成功" << endl; } bind_addr.sin_addr.S_un.S_addr = htonl(ADDR_ANY); bind_addr.sin_family = AF_INET; bind_addr.sin_port = htons(8889); //绑定ip和端口 if (bind(server_socket, (sockaddr*)&bind_addr, len) == SOCKET_ERROR) { cout << "bind error code is " << WSAGetLastError() << endl; WSACleanup(); return -1; } //开始监听 if (listen(server_socket, 5) == SOCKET_ERROR) { cout << "listen error code is " << WSAGetLastError() << endl; WSACleanup(); return -2; } //解决非阻塞的accpet while (1) { client_socket = accept(server_socket, (sockaddr*)&client_addr, &len); if (client_socket == INVALID_SOCKET) { error_code = WSAGetLastError(); if (error_code == WSAEWOULDBLOCK) { Sleep(100); continue; } else { cout << "accept失败,错误码" << error_code << endl; continue; } } else { params[0] = (LPVOID)client_socket; params[1] = (LPVOID)&client_addr; CreateThread(0, 0, (LPTHREAD_START_ROUTINE)handleThreadProc, (LPVOID)params, 0, 0); } } return 0; }