Socket编程中recv()函数出现无效参数错误(errno=22)求助
Socket读取函数调试问题
问题核心
第二次调用handle_read_socket()时,recv()返回-1且errno=22(EINVAL,无效参数),无法读取剩余的1字节数据。
代码问题分析
1. recv返回0时的错误逻辑
readsize == 0分支中,if (errno == EOF)是完全错误的:
EOF不是errno的合法取值(errno为正整数错误码,EOF定义为-1)。recv()返回0本身就表示对端正常关闭连接,此时errno的值是未定义的,不能用于判断。
2. 语法错误导致运行异常
LOG_ERROR("Could not read from client and Error happened.")语句末尾缺少分号,会导致编译错误,进而引发不可预测的运行时行为。
3. 阻塞模式下的循环逻辑问题
在阻塞模式下,当读取部分数据(如第二次调用时读取1字节,未填满缓冲区),函数会持续调用recv()阻塞等待更多数据,但单元测试中没有后续数据发送,这会导致函数挂起而非返回。
修复方案
修复后的handle_read_socket()函数
#include <string.h> // 用于strerror int handle_read_socket(struct conn *client) { int total_read = 0; int readsize = 0; while (1) { readsize = recv(client->pfd.fd, client->client_buff + total_read, BUFFSIZE - total_read, 0); if (readsize > 0) { total_read += readsize; if (total_read == BUFFSIZE) { // 缓冲区已满,退出循环 break; } } else if (readsize == 0) { // 对端关闭连接,返回错误 LOG_ERROR("Client closed connection."); return -1; } else { // 读取错误处理 if (errno == EAGAIN || errno == EWOULDBLOCK) { // 非阻塞模式下无更多数据,退出循环返回已读字节数 break; } // 其他错误,打印错误信息并返回-1 LOG_ERROR("Could not read from client: %s", strerror(errno)); return -1; } } return total_read; }
调整单元测试(启用非阻塞模式)
将socket设置为非阻塞模式,确保第二次调用时读取剩余1字节后,因无更多数据退出循环并返回:
#define BUFFSIZE 2 void test_handle_read_socket() { /* Arrangement */ struct conn sender; int sockfd[2]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) == -1) { perror("Failed creating pair sockets."); return; } // 启用非阻塞模式 int flags = fcntl(sockfd[0], F_GETFL, 0); fcntl(sockfd[0], F_SETFL, flags | O_NONBLOCK); // 写入"123"到socket sender.pfd.fd = sockfd[0]; send(sockfd[1], "123", 3, 0); eqint(2, handle_read_socket(&sender)); eqnstr("12", sender.client_buff, 2); eqint(1, handle_read_socket(&sender)); // 现在会正确返回1 eqnstr("3", sender.client_buff, 1); /* Teardown */ close(sockfd[1]); close(sockfd[0]); }
修复说明
- 修正了
recv()返回0时的错误处理逻辑,直接判断连接关闭并返回-1。 - 补全了LOG_ERROR语句的分号,修复语法错误。
- 启用非阻塞模式后,当socket无更多数据时,
recv()返回EAGAIN/EWOULDBLOCK,函数退出循环并返回已读取的字节数,符合单元测试的期望。
内容的提问来源于stack exchange,提问作者Saeedou
相关产品推荐
相关产品推荐

