当调用listen(serverSocket, 1)
时,1
表示服务器同时处理的连接请求的最大数量。在这种情况下,服务器只能处理一个客户端连接请求。如果客户端尝试连接时,服务器正在处理一个连接请求,客户端将被阻塞(即死等)直到服务器接受连接或超时。
为了解决这个问题,您可以使用多线程或异步编程模型,以便服务器能够同时处理多个连接请求。下面是一个使用多线程的简单示例:
#include <iostream>
#include <winsock2.h>#pragma comment(lib, "ws2_32.lib")// 函数原型
bool ConnectWithTimeout(SOCKET s, const sockaddr* name, int namelen, int timeout);int main() {WSADATA wsaData;if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {std::cerr << "WSAStartup 失败" << std::endl;return 1;}SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, 0);if (clientSocket == INVALID_SOCKET) {std::cerr << "创建套接字失败:" << WSAGetLastError() << std::endl;WSACleanup();return 1;}sockaddr_in serverAddr;serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(12345);serverAddr.sin_addr.s_addr = inet_addr("服务器IP地址"); // 替换为实际的服务器IP地址if (!ConnectWithTimeout(clientSocket, (sockaddr*)&serverAddr, sizeof(serverAddr), 5000)) {std::cerr << "连接服务器超时或失败" << std::endl;closesocket(clientSocket);WSACleanup();return 1;}std::cout << "已连接到服务器" << std::endl;// 在这里可以进行数据传输等操作// 关闭套接字closesocket(clientSocket);WSACleanup();return 0;
}bool ConnectWithTimeout(SOCKET s, const sockaddr* name, int namelen, int timeout) {// 设置套接字为非阻塞模式u_long mode = 1;if (ioctlsocket(s, FIONBIO, &mode) != 0) {std::cerr << "ioctlsocket 设置非阻塞模式失败:" << WSAGetLastError() << std::endl;return false;}// 尝试连接if (connect(s, name, namelen) == SOCKET_ERROR) {if (WSAGetLastError() != WSAEWOULDBLOCK) {std::cerr << "连接失败:" << WSAGetLastError() << std::endl;return false;}// 使用select进行超时等待fd_set writeSet;FD_ZERO(&writeSet);FD_SET(s, &writeSet);timeval timeoutVal;timeoutVal.tv_sec = timeout / 1000;timeoutVal.tv_usec = (timeout % 1000) * 1000;int result = select(0, nullptr, &writeSet, nullptr, &timeoutVal);if (result == SOCKET_ERROR) {std::cerr << "select 错误:" << WSAGetLastError() << std::endl;return false;} else if (result == 0) {std::cerr << "连接超时" << std::endl;return false;}}// 恢复套接字为阻塞模式mode = 0;if (ioctlsocket(s, FIONBIO, &mode) != 0) {std::cerr << "ioctlsocket 设置阻塞模式失败:" << WSAGetLastError() << std::endl;return false;}return true;
}