2010-10-15 57 views
0

我開發了(TCP)服務器來偵聽客戶端並與之交互。現在我試圖調整這個服務器代碼來收聽多個客戶端。我想要使​​用select,但是我對我發現的一些示例和解釋感到困惑。使用select()來偵聽多個客戶端(TCP)

我一直在讀:http://support.sas.com/documentation/onlinedoc/sasc/doc750/html/lr2/select.htmhttp://support.sas.com/documentation/onlinedoc/sasc/doc750/html/lr2/select.htm這兩個國家都被推薦到我..:S

第一個站點的例子似乎不太複雜。(儘管仍然不知道如何將它適應我因爲我對網絡非常非常陌生等),但我擔心由於第二個站點示例的複雜性,我錯過了關鍵方面。

下面是那種我的服務器代碼的快照時只監聽一個客戶端(包括一些僞代碼,以儘量減少不那麼重要的東西):

int main(int argc, char *argv[]) 
{ 
    int sockfd, newsockfd, portno, clilen; 
    char buffer[3]; 
    struct sockaddr_in serv_addr, cli_addr; 
    int n; 

    if (argc < 2) 
    { 
     fprintf(stderr,"ERROR, no port provided\n"); 
     exit(1); 
    } 

    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sockfd < 0){error("ERROR opening socket");} 

    bzero((char *) &serv_addr, sizeof(serv_addr)); 
    portno     = atoi(argv[1]); 
    serv_addr.sin_family  = AF_INET; 
    serv_addr.sin_addr.s_addr = INADDR_ANY; 
    serv_addr.sin_port  = htons(portno); 


    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) 
     {error("ERROR on binding");} 

    listen(sockfd,5); 

    clilen = sizeof(cli_addr); 
    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); 

    if (newsockfd < 0){error("ERROR on accept");} 


    while (UNTIL END OF FILE) 
    { 
     <DO SOME FILE READING STUFF> 

     n = write(newsockfd, "test/n", 5); 

     if (n < 0){error("ERROR writing to socket");} 


     bzero(buffer,3); 
     n = read(newsockfd,buffer,3); 

     if (n < 0){error("ERROR reading from socket");} 

     buffer[n] = 0; 

     <DO SOME STRING STUFF> 

     while(done != 1) 
     { 
      bzero(buffer,3); 
      n = read(newsockfd,buffer,3); 

      if (n < 0){error("ERROR reading from socket");} 

      buffer[n] = 0;  

      if(strcmp(buffer, "CO")) 
      { 
       done = 1; 
      } 
     } 

     done = 0; 
    } 

    <DO STUFF> 


    n = write(newsockfd, "DN\n", 2); 

    if (n < 0){error("ERROR writing to socket");} 

    close(sockfd); 
    close(newsockfd); 

    return 0; 

} 

哪個網站對選)爲例(將工作最好爲我我想要做的(更改服務器代碼來聽多個客戶端)?有人可以用一些更簡單的術語解釋select()嗎? (因爲我對這個和所有這麼新......)

謝謝!

回答

7

您需要圍繞accept()和以下代碼打包一個循環,以便您可以在程序的整個生命週期中接受多個連接。然後您需要確定您的服務器將如何處理多個連接。你有幾個選擇:

  • 使用多個線程,每個客戶端一個線程。
  • 使用分叉服務器,每個客戶端一個進程。
  • 使用一臺服務器,它將使用select()來決定哪些文件描述符已準備就緒。

在前兩種情況下,子線程或進程一心一意地處理一個客戶端;它將等待客戶端正在計劃如何響應它發送的內容,這意味着其他線程或進程會在CPU上轉向。這個主題有不同的版本,可以預先啓動一些工作者線程或進程,並安排這些工作負載來承擔工作量,但這更復雜。

在最後一種情況下,你會設置要select()工作的文件描述符的數組,然後通過該列表的副本select()(因爲它踐踏一切都結束吧)。當你有工作要做時(因爲select()返回),如果已經準備就緒,你可以在正在監聽的文件描述符上執行accept(),或者如果已準備就緒,可以從已打開的套接字描述符中讀取。