当调用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;
}