csocketsrecv

recv: Connection reset by peer


when I close my client connected to the server I get this error from the server and server shuts itself down. I know that client can terminate the connection gracefully but I am planning to send this out to some people and do not want my server to be shut just because they did not terminate gracefully. So what could actually prevent the server to be closed? I am using sys/socket.h

Here's a part of my code

int server() {
    //Set up variables
    int sockfd, new_fd;  //Listen on sock_fd, new connection on new_fd
    struct sockaddr_in my_addr;    //My(server) address information
    struct sockaddr_in their_addr; //Connector's address information
    socklen_t sin_size;
    //Generate the socket
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }
    //Generate the end point
    my_addr.sin_family = AF_INET;         //Host byte order 
    my_addr.sin_port = htons(MYPORT);     //Short, network byte order 
    my_addr.sin_addr.s_addr = INADDR_ANY; //Auto-fill with my IP 

    if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) \
    == -1) {
        perror("bind");
        exit(1);
    }

    //Start listnening
    if (listen(sockfd, BACKLOG) == -1) {
        perror("listen");
        exit(1);
    }

    while(TERMINATE == 0) {  // main accept() loop 
        sin_size = sizeof(struct sockaddr_in);
        //Create a new connection for the accepted socket
        if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, \
        &sin_size)) == -1) {
            perror("accept");
            continue;
        }
//some semaphore stuff      
    }
    return 0;
}   



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

//extra stuff

        //Set up mutex locks
        pthread_mutex_init(&mutex, NULL);
        sem_init(&empty, 0, 30);
        sem_init(&full, 0, 0);

        //Set up and run Threads
        pthread_t threads[30]; //Array of threads
        pthread_t server_thread;
        pthread_attr_t attr; //Set of thread attributes

        //Get the default thread attributes
        pthread_attr_init(&attr); 
        signal(SIGINT, termination);//Wait for a SIGINT
        //Loop to create threads and execute consumer_thread
        for (int i = 0; i < 30; i++) {
            //Set up data in structure
            threadArray[i].threadID = i;
            threadArray[i].running = 0;
            threadArray[i].line_counter_pointer = &line_counter;
            threadArray[i].vid_details_pointer = &vid_details;
            pthread_create(&threads[i],&attr,consumer_thread, &threadArray[i]); 
        }
        //Execute the producer_thread   
        pthread_create(&server_thread,&attr,producer_thread, NULL);

        //Wait for all the threads to exit
        for (int i = 0; i < 30; i++) {
            pthread_join(threads[i],NULL);
        }
        //Destroy semaphores so that it can TERMINATE gracefully
        sem_destroy(&empty);
        sem_destroy(&full);
        return 0;
    }
void *producer_thread(void *param) {
    server();//Runs the server() function
    return NULL;
}

    void *consumer_thread(void *param) {
        //Pass variable
        struct thread_params *threadStruct;
        threadStruct = (struct thread_params *) param;
        int *line_counter = threadStruct->line_counter_pointer;
        vid_details_struct *vid_details = threadStruct->vid_details_pointer;
        //End of pass   
        char found_result [MAXDATASIZE];
        int queue_item = 0;
        int numbytes;
        struct timeval item_wait_time;// Get the current time

        while (TERMINATE == 0) { //Main accept() loop
            int new_fd;
            //Use a variable that would be set to 0 after the client termination 
            //so that the current connection will be closed on both thread and 
            //client, that would make thread to go back to idle
            int current_connection = 1;
            //Acquire full semaphore
            sem_wait(&full);
            //Acquire mutex lock to protect buffer
            pthread_mutex_lock(&mutex);
    //some extra stuff including socket information
            //now handling queue[queue_item]
            new_fd = queue[queue_item].new_fd;
            queue[queue_item].waiting = 0;

            //Release mutex lock and empty semaphore
            pthread_mutex_unlock(&mutex);
            sem_post(&empty);   
            while (current_connection == 1) {
                char buf[MAXDATASIZE];
                //Receive the query
                if ((numbytes=recv(new_fd, buf, MAXDATASIZE, 0)) == -1) {
                    perror("recv");
                    exit(1);
                }           

                buf[numbytes] = '\0';//Set the end point of the string
                if (!strcmp(buf,"q")) {//Client prompts to TERMINATE
                    current_connection = 0;//Flag the connection as closed
                }
                if (current_connection == 1) {//If still connected
    //do something
                    if (send(new_fd, found_result, MAXDATASIZE, 0) == -1) {
                        perror("send");
                        close(new_fd);
                        exit(0);
                    }
                }
            }
            close(new_fd); // Close the socket connection
            //Wait for half a second before accepting a new request
            usleep(500000);
        }//End of the main while loop
        FINISHEDSEMS++;
        printf("Thread %d is closing\n", threadStruct->threadID);
        return NULL;
    }

Solution

  • This if-statement is what you need to look at:

    if ((numbytes=recv(new_fd, buf, MAXDATASIZE, 0)) == -1) {
        perror("recv");
        exit(1);
    }
    

    It's the only place you posted that has recv, so that's the error.

    Take a look at the man page: recv returns the length of the message on successful completion. If a message is too long to fit in the supplied buffer, excess bytes may be discarded depending on the type of socket the message is received from. If no messages are available at the socket, the receive calls wait for a message to arrive, unless the socket is nonblocking (see fcntl(2)), in which case the value -1 is returned and the external variable errno is set

    So instead of having a call to exit (which terminates the process), try handling the error gracefully:

    if ((numbytes=recv(new_fd, buf, MAXDATASIZE, 0)) < 0) {
        // user disconnected or timeout (if you set a timeout)
        // NO call to exit; use "continue" or "return", or something else
        // to gracefully handle the break;
        my_error_function("client disconnected\n");
        break;
    }