【问题标题】:recv: Connection reset by peerrecv:对等方重置连接
【发布时间】:2012-12-06 02:35:20
【问题描述】:

当我关闭连接到服务器的客户端时,我从服务器收到此错误并且服务器自行关闭。我知道客户端可以优雅地终止连接,但我打算将其发送给某些人,并且不希望我的服务器仅仅因为他们没有优雅地终止而关闭。那么实际上什么可以阻止服务器关闭呢? 我正在使用 sys/socket.h

这是我的代码的一部分

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

【问题讨论】:

  • 您可能想要发布至少一些代码来向我们展示您从哪里开始。您使用的是普通 TCP 套接字还是任何库(假设前者基于标签,但宁愿明确)
  • 谢谢...我是否遗漏了什么,或者如果 recv 或发送 return -1 你不能不退出?

标签: c sockets recv


【解决方案1】:

这个 if 语句是你需要看的:

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

这是您发布的唯一有recv 的地方,所以这就是错误。

看看man pagerecv返回成功完成时消息的长度。如果消息太长而无法放入提供的缓冲区,则可能会丢弃多余的字节,具体取决于接收消息的套接字类型。如果套接字上没有消息可用,则接收调用等待消息到达,除非套接字是非阻塞的(参见 fcntl(2)),在这种情况下返回值 -1 并设置外部变量 errno em>

因此,与其调用exit(终止进程),不如尝试优雅地处理错误:

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

【讨论】:

  • 我也应该关闭套接字吗?
  • 不!套接字是您的计算机和互联网之间的连接 - 关闭套接字将关闭该端口上的每个打开的连接,并且基本上会关闭服务器。您只需关闭连接,并让套接字保持打开状态。
  • 我的意思是 new_fd 变量?
  • @cegfault 是的!和垃圾。关闭套接字关闭套接字。它不会关闭任何其他套接字;它不会“关闭所有其他连接”;它不会“关闭服务器”。他应该关闭发生错误的套接字,除非它只是一个超时错误,在这种情况下,他应该尽可能多地重试他认为必要的次数。如果您谈论的是 listening 套接字,这在您的评论中并不明显,它确实会关闭服务器,但不会影响现有连接。
  • @EJP:很好的说明。是的,我的意思是监听套接字。我认为从 OP 的帖子和 cmets 中可以明显看出,当他说“套接字”时,他的代码中的意思是 sockfd = socket(...),这确实是监听套接字,不应关闭。你是对的,除非关闭套接字的代码退出主进程(这将终止所有线程和连接),否则它不会影响现有连接
【解决方案2】:

'Connection reset by peer' 有多种原因,但最常见的原因是您写入的连接已被对等方关闭。换句话说,应用程序协议错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-30
    • 1970-01-01
    • 1970-01-01
    • 2013-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多