2012-12-06 67 views
1

當我關閉我的客戶端連接到服務器我得到這個錯誤從服務器和服務器關閉。我知道客戶端可以優雅地終止連接,但我打算將它發送給某些人,並且不希望我的服務器因爲沒有正常終止而被關閉。那麼究竟是什麼可以防止服務器被關閉? 我使用SYS/socket.h中recv:連接重置由對端

這裏是我的代碼

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

你可能會想要發佈至少一些代碼,告訴我們你從哪裏開始。你使用香草TCP套接字或任何庫(假設前基於標籤,但寧願明確) – Foon

+0

我現在包括他們 –

+0

謝謝...我錯過了什麼,或者你不能不退出,如果recv或發送返回-1? – Foon

回答

2

這部分if語句是你需要看看:

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

這是你的唯一的地方發佈了recv,所以這是錯誤。

查看man pagerecv返回成功完成時的消息長度。如果消息太長而無法放入提供的緩衝區,則根據接收消息的套接字類型,可能會丟棄多餘的字節。如果套接字中沒有消息可用,則接收調用等待消息到達,除非套接字是非阻塞的(請參見fcntl(2)),在這種情況下,返回值-1並設置外部變量errno

因此而不必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; 
} 
+0

我應該關閉插座嗎? –

+1

不!套接字是您的計算機和互聯網之間的連接 - 關閉套接字將關閉該端口上的每個打開的連接,並且基本上會關閉服務器。您只關閉連接,並將套接字向上。 – cegfault

+0

我的意思是new_fd變量? –

0

有許多原因「由對等連接復位」,但最常見的是您已寫入已由對等關閉的連接。換句話說,應用程序協議錯誤。

相關問題