2015-05-27 21 views
0

我目前正試圖獲得通過AF_UNIX插座並運行的客戶端/守護通信。C++ - AF_UNIX插座掛

目前客戶端成功發送一條消息,守護進程接收和處理,然後應將郵件發送回來。
那麼,這就是問題所在。只要守護程序嘗試將消息發送回來,客戶端就會掛起,試圖讀取消息,如果我終止了客戶端,守護進程將隨着它而死。

以下是後臺代碼:

//successful call to accept, I have a file descriptor now... 
int c = 0; 
while((c = recv(fd, (char*)&buf[0], bufferSize, 0))) 
{ 
    if(c == -1 || c == 0) 
     break; 
    tmp.append(buf.begin(), buf.begin()+c); 
} 

writeLog(tmp); 
tmp = evaluateMsg(tmp); 
writeLog(tmp); 

//I assume this send call is hanging 
if(send(fd, tmp.c_str(), tmp.size(), 0) < 0) 
    writeLog("Could not write message back!"); 

close(fd); 

這是客戶端代碼:

//connect(); is successful 
//send(); as well - the recv(); call is hanging forever 
while((c = recv(sockfd, (char*)&buf[0], 1024, 0))) 
{ 
    if(c == -1) 
    { 
     cout<<"Error"; 
     break; 
    } 
    else if(c == 0) 
     break; 
    tmp.append(buf.begin(), buf.begin()+c); 
} 

請注意,該代碼是大量削減用於簡化和可讀性的原因(尤其是代碼爲daemonize並創建實際的AF_UNIX套接字(這兩個都是成功的))。

UPDATE:

我可以驗證客戶端recv()呼叫不會被恢復,這意味着守護方send()電話掛。爲什麼?

+0

客戶端之後將消息發送給你的代碼,看來它關閉套接字。那將使'發送() '失敗 –

+0

不,它不。不幸的是,這並不是那麼簡單(; –

+0

與論壇網站不同,我們不使用「謝謝」或「任何幫助表示讚賞」,或對[so]進行簽名。請參閱「[應該'嗨','謝謝''標語和稱呼從撤職?](http://meta.stackexchange.com/questions/2950/should-hi-thanks-taglines-and-salutations-be-removed-from-posts)。 –

回答

0

我沒有看到守護進程端recv()循環結束的任何原因。如果套接字仍然打開,爲什麼recv()返回0或-1?

您應該瞭解客戶端在應用程序級完成發送數據的時候,內容應該說清楚,然後完成recv()循環並繼續到服務器的send()部分。

+1

'recv()'應該返回0,如果它不能再讀取字節,不應該嗎? –

+0

實際上,我可以通過'writeLog()'調用來驗證它,這些調用向我顯示接收到的消息和處理的答案。 –

+1

@MäxMüllerAFAIK recv()在套接字被另一端關閉時返回0(有序關閉)。 – selalerer

-1

好的,解決方案非常簡單。
@selalerer說得對的recv()返回值,這導致該工作代碼片段:

while((c = recv(fd, (char*)&buf[0], bufferSize, 0))) 
{ 
    if(c == -1) 
     /* handle error */ 
    tmp.append(buf.begin(), buf.begin()+c); 

    if(c < bufferSize) 
     //no more to read, therefore stop reading 
     break; 
} 
+0

這是一個可怕的解決方案。如果另一方準確地發送'bufferSize'字節,並且一次讀取它們,您仍然會再次調用'recv'並等待永遠不會發生的數據。 (在selalerer的回答中解釋了正確的解決方法。) –

+0

嗯,你是對的,但對於我來說這是不可能的,因爲數據不能準確地得到'bufferSize'字節。但我理解你的批評,並且知道客戶應該用特定的信息結束內容。 –

+0

我懷疑你的推理不正確。只有兩種可能性。一個是消息總是小於'bufferSize'。在那種情況下,你的測試將總是*'break'。那爲什麼要測試?另一種可能性是,如果消息可能大於'bufferSize',但是如何確保您讀取的最後一部分不完全是'bufferSize'字節,在這種情況下,您將循環並等待永遠不會到達的數據。 –