Search code examples
csocketstcpesp32esp-idf

Linux Sockets - Server accepts client, but client fails with errno 127


The Problem

I am currently working on a project that requires a TCP connection between an ESP32 client and a server running on my laptop. The server side seems to be working, the server listens for connections and waits for a client socket to accept. When I start my client side ESP32, the server prints out a message "SOCKET ACCEPTED", but the client side prints "UNABLE TO CONNECT TO SERVER: ERRNO 127". I saw online that errno 127 means that the key is expired, however I was not able to find a fix to this issue. Below is the code for my server and client, any help would be greatly appreciated.

Server Code

#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...***\n");
    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);
}

Prints out "SOCKET ACCEPTED" and waits for client

Client code

//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;
}

Prints "COULD NOT CONNECT TO SERVER: ERRNO 127" and returns TCP_FAILURE.

EDIT When I try to connect to google.com, the client prints out "UNABLE TO CONNECT TO SERVER: ERRNO 113" and returns TCP_FAILURE.

If any additional information is needed please let me know. Thank you!


Solution

  • The error code 127 in ESP IDF seems to be EISCONN, "Socket is already connected".

    Your code runs in a loop. After it successfully connects to the host, the loop immediately tries again. Hence the error.