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

C语言Socket服务端仅能接受一次连接问题求助

C语言Socket客户端重复连接失败问题

问题场景

我正在学习C语言Socket编程,编写了基础的客户端和服务端程序。首次编译运行时,客户端能正常收到服务端返回的信息:

The server sent the data: You have reached the server

但再次运行客户端时,会出现如下提示:

Connection FailedThe server sent the data: 

即使终止服务端程序、重新编译并运行,问题依然存在。

客户端代码

#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>          // 包含Socket相关类型定义
#include <sys/socket.h>         // 包含Socket API
#include <netinet/in.h>         // 用于存储地址信息

int main() {
    int network_socket;         // Socket用整数值表示,后续通过该值操作Socket
    network_socket = socket(AF_INET, SOCK_STREAM, 0);  // 创建Socket,指定域、类型和协议

    struct sockaddr_in server_address;          // 创建服务端地址结构
    server_address.sin_family = AF_INET;        // 指定Socket类型为互联网域
    server_address.sin_port = htons(9002);      // 指定端口号
    server_address.sin_addr.s_addr = INADDR_ANY; // 指定服务端地址

    // 发起连接请求
    int connection_status = connect(network_socket, (struct sockaddr*) &server_address, sizeof(server_address));
    if(connection_status == -1) {
        printf("Connetion Failed");
    }

    char server_response[256];
    recv(network_socket, &server_response, sizeof(server_response), 0);

    printf("The server sent the data: %s", server_response);

    return 0;
}

服务端代码

#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main() {
    char server_message[256] = "You have reached the server\n";

    int server_socket;
    server_socket = socket(AF_INET, SOCK_STREAM, 0);

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

    bind(server_socket, (struct sockaddr*) &server_address, sizeof(server_address));
    listen(server_socket, 5);       // 5表示等待连接的最大队列长度

    int client_socket;
    client_socket = accept(server_socket, NULL, NULL);

    send(client_socket, server_message, sizeof(server_message), 0);

    return 0;
}

问题原因

  1. 服务端仅处理一次连接就终止:当前服务端在接受一个客户端连接、发送数据后直接退出进程,后续客户端发起连接时没有服务端监听端口,导致连接失败。
  2. TIME_WAIT状态占用端口:首次连接断开后,TCP连接会进入TIME_WAIT状态(默认持续2个MSL时长),此时服务端重启绑定同一端口会失败,因为端口被处于TIME_WAIT状态的连接占用。
  3. 客户端错误处理缺失:连接失败后仍执行recv操作,此时network_socket是无效句柄,recv返回错误但程序继续打印空内容,导致输出混乱。

修复方案

1. 修改服务端,支持循环处理连接并复用端口

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>  // 引入close函数头文件

int main() {
    char server_message[256] = "You have reached the server\n";

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

    // 设置端口复用,避免TIME_WAIT状态占用端口导致绑定失败
    int opt = 1;
    setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

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

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

    printf("Server listening on port 9002...\n");
    
    // 循环接受客户端连接
    while(1) {
        int client_socket = accept(server_socket, NULL, NULL);
        if(client_socket == -1) {
            perror("accept failed");
            continue;
        }
        send(client_socket, server_message, sizeof(server_message), 0);
        close(client_socket);  // 处理完连接后关闭客户端套接字
    }

    close(server_socket);
    return 0;
}

2. 完善客户端错误处理逻辑

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

int main() {
    int network_socket = socket(AF_INET, SOCK_STREAM, 0);
    if(network_socket == -1) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

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

    int connection_status = connect(network_socket, (struct sockaddr*) &server_address, sizeof(server_address));
    if(connection_status == -1) {
        perror("Connection Failed");
        close(network_socket);
        exit(EXIT_FAILURE);
    }

    char server_response[256];
    // 预留一个字节存储字符串终止符,避免乱码
    ssize_t recv_len = recv(network_socket, server_response, sizeof(server_response)-1, 0);
    if(recv_len > 0) {
        server_response[recv_len] = '\0';  // 确保字符串以'\0'结尾
        printf("The server sent the data: %s", server_response);
    } else if(recv_len == 0) {
        printf("Server closed the connection\n");
    } else {
        perror("recv failed");
    }

    close(network_socket);
    return 0;
}

关键修复说明

  • 添加SO_REUSEADDR选项:通过setsockopt设置该选项,允许服务端在TIME_WAIT状态下重新绑定端口,解决重启服务端后无法绑定的问题。
  • 服务端循环处理连接:使用while(1)持续监听并接受客户端连接,处理完单个连接后关闭客户端套接字,继续等待下一个连接。
  • 客户端错误处理优化:连接失败时直接退出程序,避免后续无效操作;recv后手动添加字符串终止符,防止打印乱码;所有操作完成后关闭套接字。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 21:35:59