2013-04-15 144 views
1

目前我正在使用單個服務器,單個客戶端udp聊天應用程序。最初我使用了默認情況下的阻塞套接字。現在我想將套接字轉換爲非阻塞狀態,以便客戶端和服務器之間的通信可以在沒有障礙的情況下完成... 我已經在服務器端實現了選擇功能,但是它啓動客戶端獲取發送一次,其中顯示在服務器端的消息,隨後客戶端和服務器得到響應,所以現在我展示瞭如何有我實現在服務器端的select()函數:c中的非阻塞套接字

  //Declaring a non-blocking structure 
       fd_set readfds,writefds; 
      // clear the set ahead of time 
       FD_ZERO(&readfds); 
       FD_ZERO(&writefds); 
      // add our descriptor to the set 
       FD_SET(sd, &readfds); 
       FD_SET(sd, &writefds); 
       /value of sd+1 
       int n=sd+1; 

由於我想要接收和發送數據,我已經在循環中實現了選擇功能:

   int client_length = (int)sizeof(struct sockaddr_in); 
       int rv = select(n, &readfds, NULL, NULL, NULL); 
       if(rv==-1) 
       { 
       printf("Error in Select!!!\n"); 
       exit(0); 
       } 
       else if(rv==0) 
       { 
       printf("Timeout occurred\n"); 
       } 
       else 
       if (FD_ISSET(sd, &readfds)) 
       { 
       int bytes_received = recvfrom(sd, buffer,SIZE, 0, (struct sockaddr *)&client, &client_length); 
       if (bytes_received < 0) 
       { 
       fprintf(stderr, "Could not receive datagram.\n"); 
       closesocket(sd); 
       WSACleanup(); 
       exit(0); 
       } 
       } 

還用於發送數據:

   fgets(buffer,SIZE,stdin); 
       int rv1 = select(n, &writefds, NULL, NULL, NULL); 
       if(rv1==-1) 
       { 
      printf("Error in Select!!!\n"); 
      exit(0); 
       } 
      else if(rv1==0) 
      { 
      printf("Timeout occurred\n"); 
      } 
      else 
      if(FD_ISSET(sd,&writefds)) 
        { 
        if(sendto(sd, buffer,strlen(buffer), 0, (struct sockaddr *) &client,client_length)<0) 
         { 
          printf("Error sending the file! \n"); 
          exit(1); 
         } 
        } 

       } 

所以我會很感激,如果somoone讓我知道是否我做這個正確與否,如果是OK,然後會在客戶端相同implelementation解決我的問題?

+0

記住'選擇()'覆蓋其輸入,所以你在每次調用該函數的時間來重新創建'fd_set's(或複製這些文件)。我不確定這是否是你的問題,但它是'select()'代碼的常見問題。 –

+0

@ Jonathan Leffler:我應該在循環中初始化「readfds」和「writefds」嗎? –

+0

是的 - 你需要在循環中初始化'readfds'和'writefds',因爲當你調用它時select()會修改它們。 –

回答

2

這是不正確的:

select(n, &writefds, NULL, NULL, NULL); 

的第二個參數是用來檢查僅出於可讀性。要檢查可寫性,使用第三個參數:

select(n, NULL, &writefds, NULL, NULL); 
+0

@ robertklep,謝謝:) –

+0

現在我有一個問題,如果我在客戶端執行相同的事情側,我應該能夠創建一個無阻塞的udp聊天應用程序,因爲到目前爲止,我已經在服務器端完成了這一點,但我仍然感到阻塞套接字... –

+0

@AaymanKhalid你必須在兩個雙方,當然:) – robertklep