2012-09-17 28 views
2

我正在嘗試使用Select呼叫的客戶端服務器代碼。但是一旦我從客戶端發送到服務器,即使客戶端在Ist數據包之後沒有發送任何東西,服務器也會連續從客戶端發送的緩衝區讀取數據。在哪裏我做錯了?服務器停留在從客戶端緩衝區持續選擇和讀取

下面的代碼片段:

fd_set readSet,master_list_read; 
FD_ZERO(&master_list_read); 
FD_SET(STDIN, &master_list_read);//stdin manually trigger reading 
FD_SET(sockfd, &master_list_read);//tcp socket 

struct timeval tv; 
int retval; 
tv.tv_sec = 10; 
tv.tv_usec = 0; 
while(1) 
{ 
bool idle=false; 
char *buffer=NULL; 
int n; 

tv.tv_sec = 10; 
readSet=master_list_read; 
retval = select(sockfd+1, &readSet, NULL, NULL,&tv); 
if (retval == -1) 
{ 
    perror("Error in select\n"); 
    exit(4); 
} 
else if(retval==0) 
{ 
    printf("*********SEND SUCCESSFUL******\n"); 
}  
else 
{ 
if(FD_ISSET(0, &readSet)) 
{ 
    bzero(buf,256); 
    fgets(buf,256,stdin); 
    if (send(sockfd, buffer,n, 0) == -1) perror("error in sending MSG to server\n"); 
} 

else if (FD_ISSET(sockfd, &readSet)) // receives data from server,print it on StdOutput 
{ 
    bzero(buf,256); 
    int nbytes = recv(sockfd, buf, 256,0); 
    if(nbytes<=0) 
    { 
     perror("recv error from server \n"); 
     exit(0); 
    } 
} 

} //END OF ELSE 
} //end of while 
close(sockfd);   
return 0; 
+0

請格式化您的代碼,使其可讀。還包括如何創建和初始化套接字。 –

+0

fd_set是一個結構,你不能指望'readSet = master_list_read'工作。閱讀[this](http://linux.die.net/man/2/select_tut),你會發現最好的方法是在每次迭代中重新初始化(FD_ZERO)fd_set。 – fvu

+4

乍一看,我注意到你只初始化了一次fd_set,但是你需要在調用select()之前每次都重新初始化它。 – Jerry

回答

6

select()呼叫您的while(1)循環離開readSet不變。這意味着稍後FD_ISSET()檢查成功。

解決方法很簡單:清除每次迭代的fd_set的:

FD_ZERO(&master_list_read); 
FD_SET(STDIN, &master_list_read); 
FD_SET(sockfd, &master_list_read); 
// only now the select() returns what you need 
retval = select(sockfd+1, &master_list_read, NULL, NULL,&tv); 

// use the master_list_read later 

只是複製FD_SET不能解決問題。