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

Linux下C++编写TCP服务端时accept返回-1的问题求助

Socket Accept 返回-1的排查建议

1. 修复accept的第三个参数(直接导致失败的核心原因)

你的accept调用中第三个参数传了NULL,这是不符合规范的错误用法。accept需要传入一个指向socklen_t变量的指针,用来存储客户端地址结构体的实际大小。修正代码如下:

sockaddr_in their_add;
socklen_t addr_len = sizeof(their_add);
int connection = accept(this->m_Socket, (sockaddr*)&their_add, &addr_len);

传NULL属于未定义行为,会直接触发accept调用失败。

2. 检查前置调用的错误(socket/bind/listen)

你的构造函数中完全没有检查socket、bind、listen的返回值,这些步骤如果失败,会导致后续accept使用无效的套接字描述符。给每个函数添加错误检查逻辑:

Server::Server(int port)
{
    m_Port = port;
    int server_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (server_socket == -1) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    sockaddr_in server_address;
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(port);
    server_address.sin_addr.s_addr = INADDR_ANY;

    if (bind(server_socket, (sockaddr *)&server_address, sizeof(server_address)) == -1) {
        perror("bind failed");
        close(server_socket);
        exit(EXIT_FAILURE);
    }

    if (listen(server_socket, SOMAXCONN) == -1) {
        perror("listen failed");
        close(server_socket);
        exit(EXIT_FAILURE);
    }

    m_Socket = server_socket;
}

常见的前置错误场景:

  • socket失败:系统资源不足或协议不支持
  • bind失败:端口被占用(错误码EADDRINUSE)、无权限绑定1024以下端口(需root权限)
  • listen失败:套接字不是有效描述符

3. 获取具体错误码定位问题

当accept返回-1时,立即打印错误信息,这是最直接的排查手段:

int connection = accept(...);
if (connection == -1) {
    perror("accept failed");
    // 或者用strerror输出更详细的错误描述
    std::cerr << "accept error detail: " << strerror(errno) << std::endl;
    continue; // 继续等待下一个连接请求
}

常见的accept错误码:

  • EBADF:传入的socket不是有效的文件描述符
  • EINVAL:套接字未处于监听状态(listen未调用或调用失败)
  • EMFILE:进程打开的文件描述符数量达到系统上限

4. 其他辅助排查点

  • 若绑定的是1024以下端口,必须用root权限运行程序,否则bind会直接失败
  • 检查目标端口是否被其他程序占用,可执行命令:netstat -tulpn | grep <你的端口号>
  • 你的代码中read后直接使用buffer构造std::string,但read不会自动添加字符串终止符,可能导致垃圾数据,建议根据read返回值处理:
    ssize_t bytes_read = read(connection, buffer, sizeof(buffer)-1);
    if (bytes_read > 0) {
        buffer[bytes_read] = '\0'; // 手动添加终止符
        std::string message(buffer);
        // 后续处理逻辑
    }
    
  • 当前代码创建线程后立即join,相当于串行处理连接,未实现真正并发,若需要并发,可改用detach或把线程存入容器管理

内容的提问来源于stack exchange,提问作者AdriaNn01

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 12:30:45