2015-04-03 112 views
1

我正在寫一個客戶端和服務器,通過Unix域套接字進行通信(對於POSIX開發類中的任務,只是爲了學習這個概念)。會發生什麼是客戶端發送命令到服務器,並且服務器解析它們並以答案迴應。我的問題是,第一個查詢到服務器不被客戶端接收,不像其他人。什麼可能導致select()不返回?

更清楚的是,客戶端沒有接收到給定服務器實例的第一個查詢,如果我關閉客戶端實例並打開一個新實例,則會收到第一個查詢。它只發生在服務器實例的第一個查詢中。

我附上了客戶端的代碼的相關部分,服務器作爲基於select()的服務器。

memset(&control, 0, sizeof(control)); 
control.sun_family = AF_UNIX; 
strcpy(control.sun_path, CLIENT_PATH); 

bind(sockfd, (struct sockaddr *)&control, sizeof(struct sockaddr_un)); 

memset(&server, 0, sizeof(server)); 
server.sun_family = AF_UNIX; 
strcpy(server.sun_path, SERVER_PATH); 

while(1) { 
FD_ZERO(&readfds); 
FD_SET(sockfd, &readfds); 
FD_SET(STDIN, &readfds); 

    if (select(sockfd+1, &readfds, NULL, NULL, NULL) < 0) { 
     close(sockfd); 
     perror("control: select"); 
     exit(1); 
    } 

    if (FD_ISSET(sockfd, &readfds)) { 
     if ((nbytes = recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL)) < 0) { 
      perror("recv"); 
     } 
     buf[nbytes] = '\0'; 
     printf(">> %s", buf); 
    } 

    if (FD_ISSET(STDIN, &readfds)) { 
     nbytes = read(STDIN, buf, sizeof buf); 
     buf[nbytes] = '\0'; 
     if (sendto(sockfd, buf, strlen(buf), 0, 
       (struct sockaddr *)&server, sizeof(struct sockaddr_un)) < strlen(buf)) { 
      perror("send"); 
     } 
    } 
} 
+2

a)'recvfrom' &&'sendto' =='UDP' b)'UDP' &&'第一個查詢到服務器沒有被客戶端接收到,不像其他的.' =='不是error'。 ...如果你想要可靠的通信,使用TCP或自己實現它或使用一些lib或... – deviantfan 2015-04-03 16:15:28

+1

關閉()後調用perror()這不是一個可靠的順序,當試圖顯示select()建議顛倒perror的順序並關閉語句 – user3629249 2015-04-03 16:41:33

+0

建議在select()(最後一個參數)上放置超時並檢查時間是否過期。發生超時時,循環返回以再次發送字符串。請記得'刷新'超時變量作爲一些操作系統(linux想到)修改該變量 – user3629249 2015-04-03 17:02:40

回答

0

參見手冊頁:http://linux.die.net/man/2/select。 「如果超時時間爲NULL(無超時),則選擇()可以無限期阻止。」您將它指定爲NULL(select()的最後一個參數),然後select()將會阻塞,直到套接字準備就緒。

所以你需要做的是分配一個結構timeval超時。 0秒0 usec timeout表示立即返回,正值表示有套接字準備使用(在您的情況下用於讀取)或超時時返回。

+0

目前還不清楚,爲select()添加一個超時將會做任何事情來解決他的潛在問題,即預期的查詢數據沒有被接收到。 – 2015-04-03 21:35:15

+0

@JeremyFriesner,我同意。我正在檢查數據是從服務器發送的,並且確實是發送的。 – Quaker 2015-04-03 22:00:04

+0

我將超時設置爲0,問題保持不變。我開始認爲這可能是事實,我'recvfrom()',然後使用有關發件人的詳細信息'sendto()'查詢答案。 – Quaker 2015-04-04 07:49:05

相關問題