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

ESP32客户端连接Linux Socket服务器异常:服务器已接受但报Errno127

问题描述

我正在开发一个ESP32客户端与笔记本电脑服务器建立TCP连接的项目。服务器能正常监听连接,启动ESP32客户端后,服务器打印“SOCKET ACCEPTED”,但客户端输出“UNABLE TO CONNECT TO SERVER: ERRNO 127”。查资料得知Errno 127表示密钥过期,但找不到解决方法。连接google.com时客户端会输出“UNABLE TO CONNECT TO SERVER: ERRNO 113”并返回TCP_FAILURE。以下是服务器和客户端代码,求帮助。

服务器代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <limits.h>

//write an error function
void error (const char *msg){
    perror(msg);
    exit(EXIT_FAILURE);
}

int main (int argc, char *argv[]){
    //function variables
    int sockFD = 0;
    int PORT = 0;
    const int MAX_CONNECTIONS;
    int n = 0;
    char buffer[255] = {' '};
    struct sockaddr_in serverAddr;
    struct sockaddr_in clientAddr;
    socklen_t cliLen;
    
    //the user should enter a port number as a command line argument
    if (argc < 2){
        printf("***PORT NUMBER NOT PROVIDED***\n");
        exit(EXIT_FAILURE);
    }

    //create the socket
    sockFD = socket(AF_INET, SOCK_STREAM, 0);
    if (sockFD < 0){
        error("***COULD NOT OPEN SOCKET***\n");
    }
    else{
        printf("***SOCKET OPENED***\n");
    }
    
    //clear the server address
    memset(&serverAddr, 0, sizeof(serverAddr));

    //get the port number
    PORT = atoi(argv[1]);

    //configure the socket
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    serverAddr.sin_port = htons(PORT);
     
    
    //bind the port to the address
    if (bind(sockFD, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) < 0){
        error("***COULD NOT BIND TO PORT***\n");
    }
    else{
        printf("***PORT BINDED***\n");
    }
  
    char hostname[HOST_NAME_MAX + 1];
    hostname[1023] = 0;
    gethostname(hostname, sizeof(hostname));
    printf("***HOSTNAME %s ***\n", hostname);
 
    //listen for incoming connections
    printf("***LISTENING...***");
    listen(sockFD, MAX_CONNECTIONS);
    cliLen = sizeof(clientAddr);
    
    //accept the connections
    sockFD = accept(sockFD, (struct sockaddr *) &clientAddr, &cliLen);
    if (sockFD < 0){
        error("***COULD NOT ACCEPT THE SOCKET***\n");
    }
    else{
        printf("***SOCKET ACCEPTED***\n");
    }
   
   
    while(true){
        //clear the buffer to ensure there is no data left over
        memset(&buffer, 0, sizeof(buffer));

        //read data from the client
        n = read(sockFD, buffer, sizeof(buffer));
        if (n < 0){
            error("***COULD NOT READ FROM THE CLIENT***\n");
        }
        printf("CLIENT: %s\n", buffer);

        //clear the buffer again
        memset(&buffer, 0, sizeof(buffer));

        //read input from the server (essentially a safer version of scanf)
        fgets(buffer, sizeof(buffer), stdin);
        if (strcmp(buffer,  "QUIT") == 0){
            break;
        }
        
        //send the data to the client
        n = write(sockFD, buffer, strlen(buffer));
        if (n < 0){
            error("***COULD NOT WRITE TO THE CLIENT***\n");
        }

        if (strcmp("QUIT", buffer) == 0){
            break;
        }
        shutdown(sockFD, 0);
        close(sockFD);
    }

    exit(EXIT_SUCCESS);
}

服务器打印“SOCKET ACCEPTED”并等待客户端数据

客户端代码
//connect to tcp server
int tcpConnect(void){
    //function variables
    int sockFD = socket(AF_INET, SOCK_STREAM, 0);
    int err = 0;
    const int PORT = 8080;
    //if I put in the domain name of my server, the client prints out 
    // "COULD NOT FIND HOST"
    const char *HOSTNAME = "ip.address.of.my.server";
    const char *TAG = "TCP CONNECT";
    struct hostent *host;
    struct sockaddr_in serverAddress;
    while(true){
        //create a socket
        if (sockFD < 0){
            ESP_LOGE(TAG, "***UNABLE TO CREATE A SOCKET: %d***\n", errno);
            return TCP_FAILURE;
        }
        //setup host parameters
        host = gethostbyname(HOSTNAME);
        if (host == NULL){
            ESP_LOGE(TAG, "***UNABLE TO FIND HOSTNAME***\n");
            return TCP_FAILURE;
        }
        
        //config the host parameter
        serverAddress.sin_family = AF_INET;
        serverAddress.sin_port = htons(PORT);
        serverAddress.sin_addr.s_addr = *(in_addr_t *) host -> h_addr;

        //connect to the server
        err = connect(sockFD, (struct sockaddr *) &serverAddress, sizeof(serverAddress));
        if (err != 0){
            ESP_LOGE(TAG, "***UNABLE TO CONNECT TO SERVER: %d***\n", errno);
            return TCP_FAILURE;
        }
        else{
            ESP_LOGI(TAG, "***CONNECTED TO THE SERVER***\n");
        }

    }
    shutdown(sockFD, 0);
    close(sockFD);
    return TCP_SUCCESS;
}

客户端打印“UNABLE TO CONNECT TO SERVER: ERRNO 127”并返回TCP_FAILURE。
补充说明:当尝试连接google.com时,客户端打印“UNABLE TO CONNECT TO SERVER: ERRNO 113”并返回TCP_FAILURE。

问题分析与解决方案

1. 客户端socket创建位置错误

客户端的sockFD = socket(AF_INET, SOCK_STREAM, 0);写在循环外部,一旦第一次连接失败,后续循环复用失效的socket句柄,直接导致connect调用报错。
修复:将socket创建移到循环内部,每次重试生成新的socket:

while(true){
    int sockFD = socket(AF_INET, SOCK_STREAM, 0);
    if (sockFD < 0){
        ESP_LOGE(TAG, "***UNABLE TO CREATE A SOCKET: %d***\n", errno);
        vTaskDelay(pdMS_TO_TICKS(1000));
        continue;
    }
    // 后续host解析、connect逻辑
}

2. 服务器MAX_CONNECTIONS未初始化

服务器中const int MAX_CONNECTIONS;未赋值,listen调用会使用垃圾值,引发异常。
修复:给变量设置合理值,比如:

const int MAX_CONNECTIONS = 5;

3. Errno编号的实际含义

ESP-IDF的errno与标准Linux有差异:

  • Errno 127实际对应socket句柄无效导致的连接失败,并非密钥过期;
  • Errno 113对应EHOSTUNREACH,说明客户端无法路由到目标主机,需检查:
    • ESP32与服务器是否在同一局域网;
    • 服务器防火墙是否开放8080端口;
    • 客户端代码中ip.address.of.my.server是否替换为服务器实际局域网IP(如192.168.x.x)。

4. 服务器循环逻辑错误

服务器循环内首次执行就调用shutdown(sockFD, 0); close(sockFD);,直接关闭连接,无法持续通信。
修复:将关闭socket代码移到循环外:

while(true){
    // 读客户端数据、写数据逻辑
    if (strcmp(buffer,  "QUIT") == 0){
        break;
    }
}
shutdown(sockFD, 0);
close(sockFD);

5. 域名解析问题

若用域名连接失败,确保ESP32已正确连接WiFi并获取DNS地址,可添加WiFi状态检查,或直接使用服务器静态IP。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 22:29:52