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

嵌入式系统TCP客户端连接服务器时卡住的问题求助

跨设备TCP连接失败:客户端卡在连接阶段

我是Socket编程新手,此前参考教程实现了本地TCP通信,现在希望实现电脑(作为服务器)与嵌入式系统(作为客户端)的跨设备TCP连接。我修改了客户端代码中servaddr.sin_addr.s_addr字段,填入了服务器的IP地址,但客户端卡在连接阶段。

服务器代码(电脑端gcc编译)

#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h> // read(), write(), close()
#define MAX 80
#define PORT 8080
#define SA struct sockaddr

// Function designed for chat between client and server.
void func(int connfd)
{
    char buff[MAX];
    int n;
    // infinite loop for chat
    for (;;) {
        bzero(buff, MAX);

        // read the message from client and copy it in buffer
        read(connfd, buff, sizeof(buff));
        // print buffer which contains the client contents
        printf("From client: %s\t To client : ", buff);
        bzero(buff, MAX);
        n = 0;
        // copy server message in the buffer
        while ((buff[n++] = getchar()) != '\n')
            ;

        // and send that buffer to client
        write(connfd, buff, sizeof(buff));

        // if msg contains "Exit" then server exit and chat ended.
        if (strncmp("exit", buff, 4) == 0) {
            printf("Server Exit...\n");
            break;
        }
    }
}

// Driver function
int main()
{
    int sockfd, connfd, len;
    struct sockaddr_in servaddr, cli;

    // socket create and verification
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        printf("socket creation failed...\n");
        exit(0);
    }
    else
        printf("Socket successfully created..\n");
    bzero(&servaddr, sizeof(servaddr));

    // assign IP, PORT
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(PORT);

    // Binding newly created socket to given IP and verification
    if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0) {
        printf("socket bind failed...\n");
        exit(0);
    }
    else
        printf("Socket successfully binded..\n");

    // Now server is ready to listen and verification
    if ((listen(sockfd, 5)) != 0) {
        printf("Listen failed...\n");
        exit(0);
    }
    else
        printf("Server listening..\n");
    len = sizeof(cli);

    // Accept the data packet from client and verification
    connfd = accept(sockfd, (SA*)&cli, &len);
    if (connfd < 0) {
        printf("server accept failed...\n");
        exit(0);
    }
    else
        printf("server accept the client...\n");

    // Function for chatting between client and server
    func(connfd);

    // After chatting close the socket
    close(sockfd);
}

客户端代码(嵌入式系统gcc编译)

#include <arpa/inet.h> // inet_addr()
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h> // bzero()
#include <sys/socket.h>
#include <unistd.h> // read(), write(), close()
#define MAX 80
#define PORT 8080
#define SA struct sockaddr
void func(int sockfd)
{
    char buff[MAX];
    int n;
    for (;;) {
        bzero(buff, sizeof(buff));
        printf("Enter the string : ");
        n = 0;
        while ((buff[n++] = getchar()) != '\n')
            ;
        write(sockfd, buff, sizeof(buff));
        bzero(buff, sizeof(buff));
        read(sockfd, buff, sizeof(buff));
        printf("From Server : %s", buff);
        if ((strncmp(buff, "exit", 4)) == 0) {
            printf("Client Exit...\n");
            break;
        }
    }
}

int main()
{
    int sockfd, connfd;
    struct sockaddr_in servaddr, cli;

    // socket create and verification
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        printf("socket creation failed...\n");
        exit(0);
    }
    else
        printf("Socket successfully created..\n");
    bzero(&servaddr, sizeof(servaddr));

    // assign IP, PORT
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = inet_addr("192.168.182.128");
    servaddr.sin_port = htons(PORT);

    // connect the client socket to server socket
    if (connect(sockfd, (SA*)&servaddr, sizeof(servaddr))
        != 0) {
        printf("connection with the server failed...\n");
        exit(0);
    }
    else
        printf("connected to the server..\n");

    // function for chat
    func(sockfd);

    // close the socket
    close(sockfd);
}

问题现象

先在电脑上运行服务器程序后,在嵌入式系统上运行客户端程序时,客户端卡在连接阶段:

root@imx8mq-var-dart:~# ./client
Socket successfully created..
(在此处无限卡住)

排查与解决步骤

1. 确认基础网络连通性

  • 在嵌入式设备上执行 ping 192.168.182.128,如果丢包或完全不通,先解决网络链路问题:
    • 检查两者是否在同一IP网段,子网掩码是否一致
    • 确认网线连接正常,交换机/路由器工作正常
    • 若跨网段,检查嵌入式设备的网关设置是否正确,能否正常访问网关
  • 同时在服务器上ping嵌入式设备的IP,确保双向连通

2. 验证服务器端口是否正常监听

在服务器终端执行:

netstat -tulpn | grep 8080

确认输出中存在0.0.0.0:8080或:::8080(对应INADDR_ANY),且进程是你的服务器程序。如果没有监听,检查服务器程序是否正常启动、有无报错。

3. 检查端口可达性

在嵌入式设备上执行以下命令测试8080端口是否能连通:

telnet 192.168.182.128 8080

或用nc工具:

nc -zv 192.168.182.128 8080

如果连接失败,大概率是服务器端的防火墙/安全组拦截了端口。

4. 关闭或配置服务器防火墙

  • Ubuntu/Debian系统:
    临时关闭防火墙测试:
    sudo ufw disable
    
    或永久添加端口允许规则:
    sudo ufw allow 8080/tcp
    
  • CentOS/RHEL系统:
    临时关闭防火墙测试:
    sudo systemctl stop firewalld
    
    或永久添加端口规则:
    sudo firewall-cmd --add-port=8080/tcp --permanent
    sudo firewall-cmd --reload
    
  • 部分杀毒软件也会拦截端口,可暂时关闭测试。

5. 代码层面的优化与检查

  • 客户端的inet_addr函数如果传入无效IP会返回INADDR_NONE,建议添加错误检查:
    in_addr_t server_ip = inet_addr("192.168.182.128");
    if (server_ip == INADDR_NONE) {
        printf("Invalid server IP address\n");
        exit(1);
    }
    servaddr.sin_addr.s_addr = server_ip;
    
  • 服务器代码中accept是阻塞调用,但只要服务器正常监听,问题根源还是在网络层面,优先排查前面的网络问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 04:40:28