2011-03-19 31 views
2

我想利用select系統調用來複STDIN和的sockfd(連接到服務器),使得我必須聽都STDIN和的sockfd並根據所在服務器的數據可供閱讀我必須繼續。使用select()系統調用監聽標準輸入和

注:#定義STDIN 0

這是當我這樣做會發生什麼。

  • 我連接到服務器的常用方法[插座(),然後連接()]
  • 我添加STDIN和連接套接字描述符「的sockfd」到FD_SET(命名爲「讀集」),意味着閱讀。
  • 然後我打電話給select()。
  • 使用FD_ISSET來確定哪個fd準備好讀取。

這個設置的問題是FD_ISSET對於fd都是正確的。一旦我得到連接到服務器我看到FD_ISSET(的sockfd,&讀集)始終是真實的,所以是FD_ISSET(STDIN,&讀集)是否,服務器發送數據或不,或者如果我從鍵盤輸入數據或沒有。

我會做什麼錯?

/*連接成功*/

FD_ZERO(&connset); 

while(1) { 

    FD_SET(sockfd,&connset); /* add sockfd to connset */ 
    FD_SET(STDIN,&connset); /* add STDIN to connset */ 
    fdmax=sockfd; 

    if(select(fdmax+1,&readset,NULL,NULL,NULL)<0){ 
     fprintf(stdout, "select() error\n"); 
     exit(0); 
    }  

    /* select returned 
    * check which socket is set 
    */ 

    if(FD_ISSET(sockfd,&connset)) { 

     /* 
     * Server sends msglen 
     * client reads msg of length msglen 
     * client prints it to stdout 
     * client waits for next activity of its listen sockets 
     */ 
     size=4; 
     ptr=(char *)&msglen; 
     while(1) { 
      if((nread=recv(sockfd,ptr,size,0)),MSG_DONTWAIT) { 
       close(sockfd); 
       exit(0); 
      } 
      size-=nread; 
      ptr+=nread; 
     } 
     bytesToRead = ntohl(msglen); 
     readbuf = (char *)malloc(sizeof(char)*(bytesToRead+1)); 
     ptr=readbuf; 
     while(1) { 
      nread=recv(sockfd,ptr,bytesToRead,MSG_DONTWAIT); 
      if(nread<=0) { 
       close(sockfd); 
       exit(0); 
      } 
      bytesToRead-=nread; 
      ptr+=nread; 
     } 
     /* msg read successfully */ 
     *ptr='\0'; 
     fprintf(stdout, "in: %s\n",readbuf); 
     free(readbuf); 
    } 

    if(FD_ISSET(STDIN,&connset)) { 
     /* data at STDIN */ 
     fgets(buf,2,stdin); /* read the first newline char (<enter>) */ 
     fprintf(stdout,"Enter msg: "); 
     fgets(buf,MAXLEN,stdin); /* read the msg */ 
     buf[strlen(buf)-1]='\0'; 
     msglen = htonl((uint32_t)(strlen(buf)-1)); 
     ptr = (char *)&msglen; 
     bytesToSend = sizeof(uint32_t); 
     cnt = bytesToSend; 
     while(cnt>0) { 
      if((nsent=send(sockfd,ptr,cnt,0))>0) { 
       cnt-=nsent; 
       ptr+=nsent; 
      } 
      else { 
       fprintf(stdout,"send error\n"); 
       exit(0); 
      } 
     } 
     ptr=buf; 
     bytesToSend=(uint32_t)(strlen(buf)-1); 
     cnt=bytesToSend; 
     while(cnt>0) { 
      if((nsent=send(sockfd,ptr,cnt,0))>0) { 
       cnt-=nsent; 
       ptr+=nsent; 
      } 
      else { 
       fprintf(stdout,"send error\n"); 
       exit(0); 
      } 
     }  
    }  
} 
return 0; 

}

+0

您是否在__every__選擇之前使用FD_SET?你能顯示一些代碼嗎? – Ptival 2011-03-19 06:59:29

+0

如何關閉此問題? – Mir 2011-03-19 07:46:27

+0

發生編程錯誤。我現在正在討論這個問題。謝謝。 – Mir 2011-03-19 08:02:59

回答

4

什麼是STDIN?有其在<stdio.h>聲明標準輸入,是一個FILE *,而不是一個文件描述符所以不能在fdset和STDIN_FILENO,這是在<unistd.h>定義並且是一個文件描述符,因此可以與fdsets使用中使用。

順便說一下,在<stdio.h>還有一個函數fileno(),它返回FILE *的文件描述符(取決於您的編譯標誌,您可能需要定義一些功能宏來獲取聲明)。

+0

#define STDIN 0 – Mir 2011-03-19 07:10:02

+1

fileno不是C標準,它只是POSIX。 unistd.h不是C標準,它只是POSIX。 – user411313 2011-03-19 07:17:45

+2

@ user411313。 fdsets和select是POSIX,我沒有看到需要提及獲取它們的參數,你需要一個POSIX函數。 – AProgrammer 2011-03-19 07:52:21