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

为何带错误检测的C语言简易服务器无法正常运行?

C简易服务器添加错误检测后无法正常运行的问题

我正在用C语言写一个简易服务器,以下代码能正常运行,访问127.0.0.1:9001时页面会显示buffer里的内容:

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>

int main()
{
    char buffer[255] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n";
    int serverSocket, clientSocket;
    serverSocket = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in serverAdress;
    serverAdress.sin_family = AF_INET;
    serverAdress.sin_port = htons(9001);
    serverAdress.sin_addr.s_addr = INADDR_ANY;
    bind(serverSocket, (struct sockaddr*)&serverAdress, sizeof(serverAdress));
    listen(serverSocket, 2);
    clientSocket = accept(serverSocket, NULL, NULL);
    send(clientSocket, buffer, sizeof(buffer), 0);
    return 0;
}

但添加错误检测后的代码却无法正常运行:移除部分错误检测(比如accept的检测)能恢复正常;移除bind的检测后有时能运行,但多数情况下页面加载一秒就断开,现象很怪异,麻烦帮忙解惑。

带错误检测的代码:

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>

int main()
{
    char buffer[255] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n";
    int serverSocket, clientSocket;

    serverSocket = socket(AF_INET, SOCK_STREAM, 0);
    if(serverSocket<0)
    {
        printf("Socket creation failed\n");
    }

    struct sockaddr_in serverAdress;

    serverAdress.sin_family = AF_INET;
    serverAdress.sin_port = htons(9001);
    serverAdress.sin_addr.s_addr = INADDR_ANY;
    bind(serverSocket, (struct sockaddr*)&serverAdress, sizeof(serverAdress));

    //if(bind(serverSocket, (struct sockaddr*)&serverAdress, sizeof(serverAdress))!=0)
    //{
    // printf("Socket bind failure\n");
    //}
    if(listen(serverSocket, 2)!=0)
    {
        printf("Listen failed\n");
    }
    clientSocket = accept(serverSocket, NULL, NULL);
    //if(clientSocket = accept(serverSocket, NULL, NULL)==-1)
    //{
    //    printf("Accept connection failed\n");
    //}
    int result=0;
    if(result=send(clientSocket, buffer, sizeof(buffer), 0)==-1)
    {
        printf("Transmission send failed\n");
    }
    //printf("%d\n", result);
    return 0;
}

问题根源分析

你的代码里有两个核心错误,都是运算符优先级导致的,还有一个隐性的错误处理逻辑问题:

  1. 被注释掉的accept检测代码:

    if(clientSocket = accept(serverSocket, NULL, NULL)==-1)
    

    ==的优先级比=高,实际执行顺序是clientSocket = (accept(...) == -1),也就是把比较结果(0或1)赋值给了clientSocket,而非accept返回的有效套接字描述符,后续send自然无法正常通信。

  2. send的错误检测代码:

    if(result=send(clientSocket, buffer, sizeof(buffer), 0)==-1)
    

    同样的优先级问题,实际是result = (send(...) == -1),即便send正常执行,你也只是把比较结果赋值给了result,而非实际发送的字节数。

  3. 错误检测后未终止程序:比如socket创建失败后,serverSocket是负数,但你没有退出程序,后续继续用这个无效套接字执行bind、listen等操作,会引发一系列连锁错误,这也是怪异现象的来源。

修复后的代码

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdlib.h> // 用于exit()函数

int main()
{
    char buffer[255] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n";
    int serverSocket, clientSocket;

    serverSocket = socket(AF_INET, SOCK_STREAM, 0);
    if(serverSocket < 0)
    {
        printf("Socket creation failed\n");
        exit(EXIT_FAILURE); // 创建失败直接终止程序
    }

    struct sockaddr_in serverAdress;
    serverAdress.sin_family = AF_INET;
    serverAdress.sin_port = htons(9001);
    serverAdress.sin_addr.s_addr = INADDR_ANY;
    
    if(bind(serverSocket, (struct sockaddr*)&serverAdress, sizeof(serverAdress)) != 0)
    {
        printf("Socket bind failure\n");
        close(serverSocket); // 关闭已创建的套接字再退出
        exit(EXIT_FAILURE);
    }

    if(listen(serverSocket, 2) != 0)
    {
        printf("Listen failed\n");
        close(serverSocket);
        exit(EXIT_FAILURE);
    }

    clientSocket = accept(serverSocket, NULL, NULL);
    if(clientSocket == -1) // 先赋值,再判断是否出错
    {
        printf("Accept connection failed\n");
        close(serverSocket);
        exit(EXIT_FAILURE);
    }

    ssize_t result = send(clientSocket, buffer, sizeof(buffer), 0);
    if(result == -1)
    {
        printf("Transmission send failed\n");
    }
    printf("Sent %zd bytes\n", result); // 打印实际发送字节数

    // 关闭所有打开的套接字,释放资源
    close(clientSocket);
    close(serverSocket);
    return 0;
}

关键修复点

  • 修正运算符优先级:先完成函数调用与赋值,再进行比较判断,避免逻辑错位。
  • 错误发生后立即终止程序,并关闭已创建的套接字,防止无效操作引发的异常。
  • send返回值类型为ssize_t,替换int避免类型截断问题。
  • 程序结束前关闭所有套接字,养成资源管理的良好习惯。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 11:24:52