You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++/Linux环境Socket服务端二次交互后进入死循环问题排查

故障根因

  • 核心错误出在recv调用的传参和返回值处理逻辑,两个问题共同导致了死循环:
    1. 接收长度参数错误:recv(newadd, buffer, strlen(buffer), 0)中buffer是刚声明的栈内存,未初始化,strlen(buffer)会返回随机值。当随机值为0时,recv会直接返回0,不会阻塞等待用户输入,循环直接进入下一轮执行写入逻辑。这里应该改为传入sizeof(buffer)指定接收缓冲区的总长度。
    2. 缺少连接断开判断:当客户端断开连接、或者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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 19:36:01