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

C语言TCP套接字连接被拒绝(errno=111)问题排查求助

TCP客户端连接服务端出现errno=111(连接被拒绝)问题排查

我使用两台虚拟机模拟客户端-服务器架构,编写了C语言TCP客户端与服务端代码,但运行时出现errno=111(连接被拒绝)错误。不过使用nc命令测试时,两台机器可正常通信,希望找到问题原因及解决方法。

客户端代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <errno.h>

int main(int argc, char ** argv) {
    //检查命令行是否传入端口
    if (argc != 2) {
        printf("Usage: %s <port>", argv[0]);
        exit(0);
    }
    //控制变量、套接字和地址相关变量
    int port = atoi(argv[1]);
    int sock;
    struct sockaddr_in addr;
    socklen_t addr_size;
    char buffer[1024];
    int n;
    //创建套接字并检查结果
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        perror("[-] Error while creating socket.\n");
        exit(1);
    }

    printf("[+] TCP socket created. \n");
    memset(&addr, '\0', sizeof(addr));//初始化地址结构体为0
    //设置地址属性
    addr.sin_family = PF_INET;
    addr.sin_port = port;
    addr.sin_addr.s_addr = INADDR_ANY;
    //连接套接字
    n = connect(sock, (struct sockaddr*)&addr, sizeof(addr));
    if (n < 0) {
        printf("Error while connecting the socket...: %s\n", strerror(errno));
        printf("Errno value = %d", errno);
        exit(1);
    }
    printf("[+] Client connected.\n");

    bzero(buffer, 1024);//清空缓冲区
    strcpy(buffer, "Hello World");
    printf("Client: %s\n", buffer);
    send(sock, buffer, strlen(buffer), 0); //发送缓冲区中的消息

    bzero(buffer, 1024);
    recv(sock, buffer, sizeof(buffer), 0); //接收服务器的响应
    printf("Server: %s\n", buffer);

    close(sock); //关闭客户端连接
    printf("[+] Disconnected from the server");

    return 0;
} 

服务端代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

int main(int argc, char** argv) {
    //检查命令行是否传入端口
    if (argc != 2) {
        printf("Usage: %s <port>", argv[0]);
        exit(0);
    }
    //定义所需变量
    int port = atoi(argv[1]); //从命令行获取端口
    int server_sock, client_sock; //服务器和客户端套接字
    struct sockaddr_in server_addr, client_addr; //服务器和客户端地址结构体(IPv4)
    socklen_t addr_size;    //地址结构体长度
    char buffer[1024];  //消息传输缓冲区
    int n;  //控制变量

    //创建服务器套接字
    server_sock = socket(AF_INET, SOCK_STREAM, 0); 
    //检查套接字创建是否成功
    if (server_sock < 0) {
        perror("[-] Error while creating socket.\n");
        exit(1);
    }

    printf("[+] TCP socket created. \n");
    //初始化服务器地址结构体为0
    memset(&server_addr, '\0', sizeof(server_addr));
    //设置服务器地址属性
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = port;
    server_addr.sin_addr.s_addr = INADDR_ANY;

    //绑定套接字到指定端口
    n = bind(server_sock, (struct sockaddr*)&server_addr, sizeof(server_addr));
    //检查绑定是否成功
    if (n < 0) {
        perror("[-] Error while binding the socket.\n");
        exit(1);
    }
    printf("[+] Socket binded to the port %d\n", port);

    //设置服务器监听状态
    int listenVar = 0;
    listenVar = listen(server_sock, 5);
    if (listenVar < 0) {
        perror("[-] Error while setup listening phase...\n");
        exit(1);
    }
    printf("[+] Listening...\n");

    //循环处理客户端连接
    while(1) {
        
        addr_size = sizeof(client_addr); //客户端地址结构体长度
        //接受客户端连接
        client_sock = accept(server_sock, (struct sockaddr*)&client_addr, &addr_size);
        if (client_sock < 0) {
            perror("[-]Error while accepting the connection");
            exit(1);
        }
        char ipString[40]; //存储客户端IP的字符串
        inet_ntop(AF_INET, &client_addr.sin_addr, ipString, sizeof(ipString)); //将IP转换为字符串格式
        printf("[+] Client connected.\n Client IP:%s\n", ipString); //打印连接的客户端IP

        bzero(buffer, 1024); //清空缓冲区
        recv(client_sock, buffer, sizeof(buffer), 0); //接收客户端消息
        printf("Client: %s\n", buffer); //打印客户端消息

        bzero(buffer,1024); //再次清空缓冲区
        strcpy(buffer, "Hi from the server"); //写入服务器响应消息
        printf("Server: %s\n", buffer); 
        send(client_sock, buffer, strlen(buffer), 0); //发送响应消息给客户端

        close(client_sock); //关闭客户端连接
        printf("[+] Client disconnected.\n");
    }

    return 0;
}

问题原因及解决方法

核心问题点

  1. 客户端目标地址错误:客户端代码中addr.sin_addr.s_addr = INADDR_ANY;是错误用法——INADDR_ANY是服务端用来绑定所有网卡地址的参数,客户端连接时必须指定服务端虚拟机的真实IP地址,否则客户端会尝试连接自身虚拟机的对应端口,自然被拒绝。
  2. 端口未转换为网络字节序:客户端和服务端代码中,sin_port直接赋值为port,没有使用htons()函数将主机字节序转换为网络字节序,这会导致端口解析错误,服务端绑定的端口和客户端尝试连接的端口实际不匹配。
  3. 客户端参数缺失:当前客户端仅要求传入端口,没有传入服务端IP的参数,无法指定正确的连接目标。

具体修复步骤

客户端代码修改

  • 调整命令行参数要求:将argc != 2改为argc != 3,用法提示改为Usage: %s <server_ip> <port>,支持传入服务端IP和端口。
  • 设置正确的服务端IP:用inet_addr(argv[1])将命令行传入的IP字符串转换为网络字节序,赋值给addr.sin_addr.s_addr。
  • 端口转换为网络字节序:用htons(port)替换直接赋值的port。

修改后的客户端核心代码片段:

if (argc != 3) {
    printf("Usage: %s <server_ip> <port>", argv[0]);
    exit(0);
}
int port = atoi(argv[2]);
// ...
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(argv[1]);

服务端代码修改

将绑定端口的代码改为网络字节序:

server_addr.sin_port = htons(port);

运行注意事项

  • 先启动服务端,确认输出[+] Listening...后再启动客户端。
  • 客户端启动时传入服务端虚拟机的真实IP和端口,例如:./client 192.168.1.100 8080。
  • 确保两台虚拟机的防火墙已开放对应端口(如8080),避免被防火墙拦截连接。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 00:54:54