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

