C++/Linux环境Socket服务端二次交互后进入死循环问题排查
故障根因
- 核心错误出在
recv调用的传参和返回值处理逻辑,两个问题共同导致了死循环:- 接收长度参数错误:
recv(newadd, buffer, strlen(buffer), 0)中buffer是刚声明的栈内存,未初始化,strlen(buffer)会返回随机值。当随机值为0时,recv会直接返回0,不会阻塞等待用户输入,循环直接进入下一轮执行写入逻辑。这里应该改为传入sizeof(buffer)指定接收缓冲区的总长度。 - 缺少连接断开判断:当客户端断开连接、或者
recv执行出错时,recv会返回0或负数,你没有对该返回值做判断,也没有关闭当前客户端套接字newadd,导致while (newadd > 0)的判断始终成立,循环无限执行。
- 接收长度参数错误:
- 额外优化点:
listen只需在端口绑定后调用1次即可,不需要放在客户端处理循环中重复调用;另外代码中定义的队列大小参数que没有实际使用,listen的第二个参数写死为1,你可以改为传入que变量使用自定义队列大小。
修复后代码示例
#include <sys/socket.h> #include <iostream> #include <stdio.h> #include <stdlib.h> #include <netdb.h> #include <netinet/in.h> #include <string.h> #include <vector> #include <sys/types.h> #include <unistd.h> #include <cstring> int main(int argc, char* argv[]){ int socketfd = 0; int portin = 5514; //default port int que = 20; //default queue size int n = 0; int d = 1; //for use in setsockopt socklen_t clientsize = 0; struct sockaddr_in servadd, cliadd; if (argc > 2) portin = atoi(argv[2]); if (argc > 1) que = atoi(argv[1]); socketfd = socket(AF_INET, SOCK_STREAM, 0); setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, &d, sizeof(int)); bzero((char*) &servadd, sizeof(servadd)); servadd.sin_family = AF_INET; servadd.sin_addr.s_addr = INADDR_ANY; servadd.sin_port = htons(portin); bind(socketfd, (struct sockaddr*) &servadd, sizeof(servadd)); // listen只调用一次,使用传入的队列大小参数 listen(socketfd, que); std::cout << "Wall server running on port " << portin << " with queue size " << que << "." << std::endl; char wallc[] = "Wall Contents\n-------------\n"; char entc[] = "Enter command: "; do { clientsize = sizeof(cliadd); int newadd = accept(socketfd, (struct sockaddr*)&cliadd, &clientsize); while (newadd > 0) { char buffer[80]; n = write(newadd, wallc, sizeof(wallc)); n = write(newadd, entc, strlen(entc)); // 修正接收长度为缓冲区总大小,预留1位存字符串结束符 int a = recv(newadd, buffer, sizeof(buffer)-1, 0); // 处理连接断开/出错的情况 if (a <= 0) { close(newadd); break; } buffer[a] = '\0'; // 补充字符串结束符,方便后续处理命令 // 这里可以补充自定义命令处理逻辑 memset(buffer, 0, 80); }; }while (socketfd > 0); close(socketfd); return 0; }
内容的提问来源于stack exchange,提问作者DannyS
相关产品推荐
相关产品推荐

