2015-05-27 22 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'字节,在这种情况下,您将循环并等待永远不会到达的数据。 –