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

C语言Socket服务端仅能发送单条消息问题排查求助

C语言Socket通信问题:服务端无法响应客户端WORD消息

我用C语言写的Socket服务端,现在只能给客户端发送HELLO消息,客户端发送WORD消息后,服务端本该返回GREEK,但一直发不出去。已经确认connect、bind、socket、listen、accept这些调用都没问题,试过write、send等多种发送方式还是不行。

服务端核心代码

while (1) {
    if ((newsockfd = accept(sockfd, (struct sockaddr *)&dest, &destlen)) == -1) {
        perror("Accept call failed");
        exit(-1);
    }

    if ((childpid = fork()) == 0) {
        //close(sockfd);
        talk_to_client(newsockfd);
        //close(newsockfd); 
    }
    else if (childpid > 0)  {
        //close(newsockfd);
    }
}
}

talk_to_client()函数代码

void talk_to_client(int sockfd) {
    char message[1024] = "HELLO";
    char message2[1024] = "GREEK";
    char recieved[1024];
    ssize_t n;
    //cannot send more than one!!!!!!!!! WHY NOT
    write(sockfd, message, sizeof(message));
    while (1) {
        recv(sockfd, recieved, sizeof(recieved), 0);
        if (recieved == "WORD") {
            //send initial word
            printf("SENDING WORD");
            write(sockfd, message2, sizeof(message2));
        }
        if (recieved == "QUIT") {
            //close connection
            close(sockfd);
        }

    }
    return;
}

客户端核心代码

char srv[512];

char cli[512] = "WORD";
// Connects socket to server
rv = connect(sockfd, (struct sockaddr *) servaddr, sizeof(struct sockaddr));
if (rv == -1){
    perror("Error connecting to the server");
    exit(-1);
}       
if(recv(sockfd, srv, sizeof(srv), 0) == -1) {
    perror("Client receiving error");
}

printf("Client received: %s\n", srv);

if(send(sockfd, cli, sizeof(cli), 0) == -1){
    perror("Error sending message to the server");
    exit(-1);
}
printf("Client sending: %s\n", cli);

if(recv(sockfd, srv, sizeof(srv), 0) == -1) {
    perror("Client receiving error");
}
printf("Client received: %s\n", srv);

close(sockfd);

当前输出

Client received: HELLO
Client sending: WORD
Client received:

问题根源

  • 字符串比较错误:C语言中不能用==直接比较字符串内容,这是在比较两个字符串的指针地址,肯定不相等。必须用strcmp()函数来比较字符串内容。
  • 发送数据长度错误:不管是服务端发HELLO,还是客户端发WORD,都用了sizeof()来指定发送长度,这会把整个数组的1024/512字节都发出去,包括后面的空字符,导致服务端接收到的内容不是纯"WORD",strcmp自然匹配不上。应该发送字符串的实际长度,用strlen() + 1(加1是为了包含终止符\0)。
  • recv返回值未处理:recv的返回值表示实际接收到的字节数,不处理的话不知道有没有接收到数据,甚至可能接收失败还在继续处理。而且recv后需要手动给缓冲区加终止符,否则字符串函数会读取到垃圾数据。
  • 服务端循环未处理客户端断开:当客户端断开连接后,recv会返回-1,此时应该退出循环并关闭socket。

修改后的关键代码片段

服务端talk_to_client函数修改:

void talk_to_client(int sockfd) {
    char message[1024] = "HELLO";
    char message2[1024] = "GREEK";
    char recieved[1024];
    ssize_t n;

    // 只发送实际字符串长度(包含\0)
    write(sockfd, message, strlen(message) + 1);

    while (1) {
        // 接收数据并检查返回值,预留一个字节给终止符
        n = recv(sockfd, recieved, sizeof(recieved) - 1, 0);
        if (n <= 0) {
            // 客户端断开或接收失败,退出循环
            close(sockfd);
            break;
        }
        // 手动添加字符串终止符
        recieved[n] = '\0';

        if (strcmp(recieved, "WORD") == 0) {
            printf("SENDING WORD\n");
            // 发送GREEK的实际长度
            write(sockfd, message2, strlen(message2) + 1);
        }
        if (strcmp(recieved, "QUIT") == 0) {
            close(sockfd);
            break;
        }
    }
    return;
}

客户端发送部分修改:

// 只发送WORD的实际长度(包含\0)
if(send(sockfd, cli, strlen(cli) + 1, 0) == -1){
    perror("Error sending message to the server");
    exit(-1);
}

另外,建议补上服务端fork后、客户端退出时的socket关闭操作,避免资源泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 01:31:08