写了一个select非阻塞的服务器端程序,但是同时启动2个客户端去连接的话会出现问题。2个客户端都可以连接成功,但是只有第二个连接的客户端发送的信息可以被正确接收到,第一个客户端发送的消息,一直出错,错误号是10035,即WSEAWOULDBLOCK,,,我很奇怪为什么会一直都无法接收。还有很多其他的问题,不一一叙述,我没自己写客户端程序,使用的是TCP&UDP测试工具进行测试的
WSADATA Wsadata; SOCKET Server; SOCKET Client; SOCKADDR_IN serverAddr; SOCKADDR_IN clientAddr; //保存所有客户端socket的数组 vector<SOCKET> clientSockets; int index = 0; FD_SET ReadSet; //初始化环境 if (WSAStartup(MAKEWORD(2, 1), &Wsadata) != 0) { fprintf(stderr, "Init socket failed, error: %d\n", GetLastError()); WSACleanup(); return -1; } Server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (Server == INVALID_SOCKET) { fprintf(stderr, "Create socket failed, error: %d\n", GetLastError()); closesocket(Server); WSACleanup(); return -1; } //设置为非阻塞模式 unsigned long mode = 1; if (ioctlsocket(Server, FIONBIO, &mode) != 0) { return -1; } //设置 serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(8888); serverAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //绑定 int ret = bind(Server, (SOCKADDR*)&serverAddr, sizeof(SOCKADDR_IN)); if (ret != 0) { fprintf(stderr, "Bind socket failed, error: %d\n", GetLastError()); closesocket(Server); WSACleanup(); return -1; } printf("绑定成功...\n"); //监听 ret = listen(Server, 10); if (ret != 0) { fprintf(stderr, "listen socket failed, error: %d\n", GetLastError()); closesocket(Server); WSACleanup(); return -1; } printf("启动监听...\n"); while (1) { struct timeval tv; tv.tv_sec = 2; tv.tv_usec = 0; FD_ZERO(&ReadSet); for (int i = 0; i < index; i++) { //将所有的客户端放入集合中 FD_SET(clientSockets[i], &ReadSet); } //将服务器的socket放入集合中 FD_SET(Server, &ReadSet); if (select(0, &ReadSet, NULL, NULL, &tv) == SOCKET_ERROR) { fprintf(stderr, "select error: %d\n", GetLastError()); closesocket(Server); WSACleanup(); return -1; } if (FD_ISSET(Server, &ReadSet)) { int len = sizeof(clientAddr); //接收 Client = accept(Server, (SOCKADDR*)&clientAddr, &len); if (Client != INVALID_SOCKET) { //将已经连接的客户端保存到数组中 clientSockets.push_back(Client); index++; printf("连接成功.\n"); } else { continue; } }//end if for (int i = 0; i < clientSockets.size(); ++i) { if (FD_ISSET(clientSockets[i], &ReadSet)) { Sleep(1); char buf[256]; memset(buf, 0, sizeof(buf)); int ret = recv(Client, buf, sizeof(buf)-1, 0); if (ret == SOCKET_ERROR) { if (GetLastError() == WSAEWOULDBLOCK) { continue; } else { fprintf(stderr, "recv error : %d\n", GetLastError()); closesocket(clientSockets[i]); clientSockets[i] = NULL; index--; return -1; } } if (ret == 0) { closesocket(clientSockets[i]); clientSockets.erase(clientSockets.begin() + i); i--; index--; printf("断开连接.\n"); continue; } printf("接受信息内容 :%s\n", buf); }//end if }//end for //将获得的消息存储在消息队列中 } //关闭socket,清理环境 closesocket(Server); closesocket(Client); WSACleanup(); return -1;
解决方案:30分
for (int i = 0; i < index; ++i) { if (FD_ISSET(clientSockets[i], &ReadSet)) { Sleep(1); char buf[256]; memset(buf, 0, sizeof(buf)); int ret = recv(Client, buf, sizeof(buf)-1, 0); if (ret == SOCKET_ERROR) { if (GetLastError() == WSAEWOULDBLOCK) { continue; } else { fprintf(stderr, "recv error : %d\n", GetLastError()); closesocket(clientSockets[i]); clientSockets[i] = NULL; index--; return -1; } } if (ret == 0) { closesocket(clientSockets[i]); clientSockets.erase(clientSockets.begin() + i); i--; index--; printf("断开连接.\n"); continue; } printf("接受信息内容 :%s\n", buf); }//end if }//end for //put it at the end, every sockets in the vector were put into the fd set if (FD_ISSET(Server, &ReadSet)) { int len = sizeof(clientAddr); //接收 Client = accept(Server, (SOCKADDR*)&clientAddr, &len); if (Client != INVALID_SOCKET) { //将已经连接的客户端保存到数组中 clientSockets.push_back(Client); index++; printf("连接成功.\n"); } else { continue; } }//end if