C语言服务端使用select()时客户端无法接收欢迎消息问题排查
故障根因分析
你代码的核心错误出在服务端accept()函数的参数使用不符合规范:
accept()的第三个参数要求传入socklen_t类型的指针,指向存储地址结构体长度的变量,而你直接传入了sizeof(address)这个整型常量,相当于把一个整数当作内存地址传递给内核,会触发非法内存访问,accept()调用大概率会失败返回-1。后续你向无效的文件描述符执行send()操作,数据自然无法发送到客户端。- 所有系统调用(socket、bind、listen、accept、send等)都没有做返回值校验,你无法感知到调用失败的问题,自然也没办法第一时间定位故障点。
- 非本次故障的直接问题,但属于不规范写法:客户端的
serverAddress.sin_addr.s_addr填了INADDR_ANY,虽然本机测试可以临时生效,但规范写法应该填写服务端的实际IP,本机测试填htonl(INADDR_LOOPBACK)(对应127.0.0.1)更合理;recv()的第二个参数不需要对数组取地址,数组名本身就是首地址指针。
你之前不用select()的版本能正常运行属于栈内存布局巧合:你传入的非法整型值刚好被当作指针时,指向的内存区域存储的值恰好等于地址结构体的长度,相当于侥幸蒙对了参数,切换实现后栈布局变化就触发了原本就存在的隐藏bug。
修复方案
只需要修改服务端accept()调用的相关逻辑即可:
// 在accept调用前先定义存储地址长度的变量 socklen_t addr_len = sizeof(address); // 传入地址长度变量的指针作为第三个参数 int accepted_socket = accept(master_socket, (struct sockaddr *)&address, &addr_len); // 增加错误校验,避免后续无效操作 if (accepted_socket < 0) { perror("accept失败"); continue; }
修改后重新编译运行即可正常收到欢迎消息。
内容的提问来源于stack exchange,提问作者user16984278
相关产品推荐
相关产品推荐

