1

I receive an error on client-side code about connection reset by peer when I call the function send from client --> server. I looked it on the internet, but I don't understand it thoroughly, can someone explain what triggers this error and why?

This is the code for client socket. I made it accept a server on 127.0.0.1.

CLIENT.C

#define _GNU_SOURCE
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <semaphore.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <errno.h>

#define SERVER_PORT 9002
#define BUFSIZE 4096
#define SOCKETERROR (-1)
#define SERVER_BACKLOG 1

typedef struct sockaddr_in SA_IN;
typedef struct sockaddr SA;

struct sockaddr_in init_socket(const char* address);
void check(int output,const char* msg);

int main(int argc,char** argv){

int     number = 0;
int     client_socket;
SA_IN   client_address;


check((client_socket = socket(AF_INET,SOCK_STREAM,0)),"[SERVER] : cannot create socket");
client_address = init_socket("127.0.0.1");
check(connect(client_socket,(struct sockaddr*)&client_address,sizeof(client_address)),"[CLIENT]--(connect)--->[SERVER] ");

 while(1){ 
    if(send(client_socket,&number,sizeof(number),0),"[CLIENT]-------->[SERVER] " > 0){

        number++;
        if(number == 100) break;
        printf("[CLIENT] : %d\n",number);

        check(recv(client_socket,&number,sizeof(int),0),"[CLIENT]-------->[SERVER] ");
    }
}
close(client_socket);
return 0;
}

struct sockaddr_in init_socket(const char* address){
    struct sockaddr_in server_address;
    server_address.sin_family       = AF_INET; 
    server_address.sin_port         = htons(SERVER_PORT);
    // server_address.sin_addr.s_addr  = INADDR_ANY;
    server_address.sin_addr.s_addr  = inet_addr(address);
    return server_address;
}

void check(int output,const char* msg){
    if(output < 0){
        perror(msg);
        exit(1);
    }
}

This is the code for the server socket. It accepts clients from any address( INADDR_ANY).

SERVER.C

#define _GNU_SOURCE
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <semaphore.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <errno.h>

#define SERVER_PORT 9002
#define BUFSIZE 4096
#define SOCKETERROR (-1)
#define SERVER_BACKLOG 1

typedef struct sockaddr_in SA_IN;
typedef struct sockaddr SA;

void handle_connection(int client_socket);
struct sockaddr_in init_socket();
void check(int output,const char* msg);

int main(int argc,char** argv){

    int     number;
    int     server_socket   , client_socket;
    SA_IN   server_address  ,client_address;
    
    check((server_socket = socket(AF_INET,SOCK_STREAM,0)),"[SERVER] : cannot create socket");
    server_address = init_socket();
    check(bind(server_socket,(SA*)&server_address,sizeof(server_address)),"[SERVER] : binding error");
    check((client_socket = listen(server_socket,SERVER_BACKLOG)),"[SERVER] : listen failed");

     while(1){ 
        if(recv(client_socket,&number,sizeof(int),0) > 0){


            number++;
            if(number == 100) break;
            printf("[SERVER] : %d\n",number);

            check(send(client_socket,&number,sizeof(number),0),"[SERVER]-------->[CLIENT]: ERROR");
        }
    }
    close(server_socket);
    return 0;
}

struct sockaddr_in init_socket(){
    struct sockaddr_in server_address;
    server_address.sin_family       = AF_INET; 
    server_address.sin_port         = htons(SERVER_PORT);
    server_address.sin_addr.s_addr  = INADDR_ANY;
    return server_address;
}

void check(int output,const char* msg){
    
    if(output < 0){
        fprintf(stderr,"%s\n",msg);
        exit(1);
    }
}
Rabi
  • 15
  • 1
  • 3
  • Remember that TCP is a *streaming* protocol. The data being transmitted is just a stream of bytes. There are no message boundaries or separators. Therefore it can often happen that a single "message" sent over a TCP socket might not be received in full in the other end. When you receive from a socket, you must know exactly how much to receive and do it in a loop until you have received the full message. Highly unlikely in your case when you only transmit an `int`, but something to remember for future programs. – Some programmer dude May 17 '22 at 09:05
  • It means the other side closed the socket. – user253751 May 17 '22 at 09:06
  • 1
    You aren't reacting correctly to end of stream in the client, so you keep sending after the server has disconnected, so when you keep sending you get a connection reset. Solution: react correctly to end of stream, by closing the socket. No doubt that is what `check()` is supposed to do, but it doesn't. – user207421 May 17 '22 at 11:37

1 Answers1

-1

The "connection reset by peer" is exactly what it sounds like: The "peer" (the other side of the connection) have closed the connection.

Normally you discover it by checking if the socket is readable, and with read (or recv) returning 0.

If you don't detect it that way, and instead attempt to write to the socket you will get the error you're getting.

If you get that error (or detect the closed connection the other way) then you should close your end of the connection.


The specific problem with your code is that your check function only checks for errors, not other conditions that might apply (like the closed connection).

It's almost always a good idea to save what read or recv returns in a variable that you can check for explicit errors (-1) or closed connection (0) or data successfully received (> 0).

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621