Search code examples
csocketstcp

Error with TCP sockets connection in C language


I had already post a question about this problem but I don't find any answer and also the post is now closed and I don't know why?? However, I repost the question.

I want to connect two TCP sockets in a simple client-server architecture, and I setup two VMs to simulate two machines that want to communicate.

Here the client code:

#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) {
    //controllo che la porta venga indicata in riga di comando
    if (argc != 2) {
        printf("Usage: %s <port>", argv[0]);
        exit(0);
    }
    //variabili di controllo, socket e indirizzo
    int port = atoi(argv[1]);
    int sock;
    struct sockaddr_in addr;
    socklen_t addr_size;
    char buffer[1024];
    int n;
    //chiamata a socket e subito dopo controllo
    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));//setto i byte a 0
    //imposto gli attributi dell'indirizzo
    addr.sin_family = PF_INET;
    addr.sin_port = port;
    addr.sin_addr.s_addr = INADDR_ANY;
    //connetto la socket
    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);// azzero i byte del buffer
    strcpy(buffer, "Hello World");
    printf("Client: %s\n", buffer);
    send(sock, buffer, strlen(buffer), 0); // mando il messaggio contenuto nel buffer

    bzero(buffer, 1024);
    recv(sock, buffer, sizeof(buffer), 0); //ricevo la risposta del server 
    printf("Server: %s\n", buffer);

    close(sock); // chiudo la connessione lato client
    printf("[+] Disconnected from the server");

    return 0;
} 

And here is the server code:

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

int main(int argc, char** argv) {
    //controllo che da riga di comando venga inserita la porta a cui collegare la socket
    if (argc != 2) {
        printf("Usage: %s <port>", argv[0]);
        exit(0);
    }
    //creo tutte le variabili che mi serviranno 
    int port = atoi(argv[1]); //porta presa da riga di comando
    int server_sock, client_sock; //socket per server e client 
    struct sockaddr_in server_addr, client_addr; //struct per gestire gli indirizzi di server e client(IPv4, IPv6)
    socklen_t addr_size;    //lunghezza degli indirizzi
    char buffer[1024];  //buffer per il trasferimento dei messaggi
    int n;  //variabile di controllo

    //chiamata alla funzione socket che restituisce un valore int a server_sock
    server_sock = socket(AF_INET, SOCK_STREAM, 0); 
    //controllo che la chiamata socket() abbia restituito un valore > 0, quindi esito della chiamata positivo
    if (server_sock < 0) {
        perror("[-] Error while creating socket.\n");
        exit(1);
    }

    printf("[+] TCP socket created. \n");
    //setto i byte della memoria a 0
    memset(&server_addr, '\0', sizeof(server_addr));
    //assegno i vari attributi dell'indirizzo
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = port;
    server_addr.sin_addr.s_addr = INADDR_ANY;

    //chiamata alla funzione bind che associa la socket con la porta e ne metto il valore di ritorno in n 
    n = bind(server_sock, (struct sockaddr*)&server_addr, sizeof(server_addr));
    //controllo che la chiamata precedente sia andata bene quindi n > 0
    if (n < 0) {
        perror("[-] Error while binding the socket.\n");
        exit(1);
    }
    printf("[+] Socket binded to the port %d\n", port);

    //metto in ascolto il server
    int listenVar = 0;
    listenVar = listen(server_sock, 5);
    if (listenVar < 0) {
        perror("[-] Error while setup listening phase...\n");
        exit(1);
    }
    printf("[+] Listening...\n");

    //ciclo su i client che si collegano al server
    while(1) {
        
        addr_size = sizeof(client_addr); // size dell'indirizzo del client
        //chiamata alla funzione accept, che restituisce un valore int 
        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]; // stringa per salvare l'ip del client che si è collegato al server
        inet_ntop(AF_INET, &client_addr, ipString, sizeof(client_addr)); //converto l'ip in un formato di testo
        printf("[+] Client connected.\n Client IP:%s\n", ipString); //stampo l'indirizzo che si è collegato al server

        bzero(buffer, 1024); //azzero i byte del buffer
        recv(client_sock, buffer, sizeof(buffer), 0); //ricevo il messaggio dal client
        printf("Client: %s\n", buffer); // stampo il messaggio salvato in buffer

        bzero(buffer,1024); //riazzero il buffer 
        strcpy(buffer, "Hi from the server"); // passo una stringa nel buffer
        printf("Server: %s\n", buffer); 
        send(client_sock, buffer, strlen(buffer), 0); // mando il messaggio del buffer al client

        close(client_sock); //chiudo la connessione 
        printf("[+] Client disconnected.\n");
    }

    return 0;
}

I have a problem with the function control, and the errno return value 111, or connection refused, but I don't understand why. I think there is no connection setup problem, because if I execute the nc command on the machines, they both communicate without a problem.


Solution

  • On the client side, INADDR_ANY (0.0.0.0) is not a valid IP address to connect() to. On the server side, you can bind() a server socket to INADDR_ANY to listen on all local network interfaces.

    You need to specify the server's actual IP address when calling connect(). Since your client and server are running in separate VMs, the server VM needs to have a public IP address assigned to it which is reachable from the client VM.

    Also, you need to use htons() when assigning a value to the sinaddr_in::sin_port field.