Windows Select模型Socket客户端收不到服务器返回数据问题排查
Windows下Select模型Socket客户端无法接收数据的排查与解决
看起来你遇到的问题核心在于对Windows平台下select函数第一个参数的理解偏差,以及fd_set的使用方式问题,我来一步步帮你拆解:
问题1:select第一个参数传值错误
Windows和Unix平台的select函数第一个参数确实有差异,但你可能没抓准关键点:
- 在Unix系统中,这个参数是最大文件描述符值+1;
- 在Windows系统中,这个参数表示的是需要检查的套接字句柄的范围,同样要求传入最大的套接字句柄值+1,而不是你代码里的连接数
CLIENT_SIZE。
你的代码中create_socket返回的套接字句柄在Windows下通常是一个较大的数值(远大于1),而你传入select(CLIENT_SIZE, ...)也就是select(1, ...),这会导致select只检查句柄值小于1的套接字,完全不会处理你创建的那个真实socket的读事件,自然永远触发不了收数据的代码块。
问题2:未重新构建fd_set集合
select函数会修改传入的fd_set集合,把没有事件发生的套接字从集合中移除。你的代码只在初始化时构建了一次fd_read集合,第一次select后,如果读事件没触发,fd_read里就不再包含你的socket了,后续循环的select根本不会再监听它的读事件。
修复方案
针对这两个问题,修改你的代码:
1. 跟踪最大套接字句柄值
在创建socket时记录最大的句柄值,传给select:
// 在main函数中,创建socket循环里添加 SOCKET max_sock = 0; for (int i = 0; i < CLIENT_SIZE; i++) { SOCKET sock = create_socket(); socks[i] = sock; if (sock > max_sock) { max_sock = sock; // 记录最大的socket句柄 } FD_SET(sock, &fd_write); FD_SET(sock, &fd_read); }
2. 修正select的第一个参数
把原来的select(CLIENT_SIZE, ...)改成:
int ret = select(max_sock + 1, &fd_read, &fd_write, NULL, &tv);
3. 每次循环重新构建fd_set
把FD_ZERO和FD_SET的逻辑移到while循环内部,确保每次select都监听所有需要关注的socket:
// 添加一个数组标记是否已发送数据,避免重复触发写事件 bool sent[CLIENT_SIZE] = {false}; while (number_to_recv > 0) { // 每次循环重置fd集合 FD_ZERO(&fd_read); FD_ZERO(&fd_write); for (int i = 0; i < CLIENT_SIZE; i++) { FD_SET(socks[i], &fd_read); // 始终监听读事件 if (!sent[i]) { FD_SET(socks[i], &fd_write); // 只对未发送的socket监听写事件 } } int ret = select(max_sock + 1, &fd_read, &fd_write, NULL, &tv); for (int i = 0; i < CLIENT_SIZE; i++) { if (FD_ISSET(socks[i], &fd_read)) { char buf[BUF_SIZE]; int n = recv(socks[i], buf, BUF_SIZE, 0); if (n > 0) { buf[n] = 0; printf("%s\n", buf); number_to_recv--; } else if (n == 0) { // 服务器关闭连接 number_to_recv--; closesocket(socks[i]); } else { printf("Recv Error::%d\n", GetLastError()); number_to_recv--; closesocket(socks[i]); } } if (FD_ISSET(socks[i], &fd_write)) { send_data(socks[i]); sent[i] = true; // 标记为已发送,不再监听写事件 } } }
另外,我在recv逻辑里补充了错误处理,这样能帮你更好地排查可能出现的其他问题。
内容的提问来源于stack exchange,提问作者Xu Wang
相关产品推荐
相关产品推荐

