【问题标题】:why when writting more than once to socket, it blocks?为什么多次写入套接字时,它会阻塞?
【发布时间】:2010-01-11 03:40:09
【问题描述】:

我遇到了套接字问题,如果您能提供帮助,我会很高兴...
问题是当我多次发送数据时它会阻塞,例如:

//--- client ---  
//..
send(sock, buf_1, sizeof(buf_1), 0);  

for (x10){   
//...  
send(sock, buf_2, sizeof(buf_2), 0);    
if (recv(sock, buf_2, sizeof(buf_2), 0)<0) printf("recv_2() failed");   
//...   
}  

for (x20){   
//...  
send(sock, buf_3, sizeof(buf_3), 0);     
if (recv(sock, buf_3, sizeof(buf_3), 0)<0) printf("recv_3() failed");   
//...    
}  
//...          

//--- server---   
//...  
if (recv(sock, buf_1, sizeof(buf_1), 0)<0) printf("recv_1() failed"); 

for (x10){     
if (recv(sock, buf_2, sizeof(buf_2), 0)<0) printf("recv_2() failed");    
//...    
send(sock, buf_2, sizeof(buf_2), 0);     
}     

for (x20){   
if (recv(sock, buf_3, sizeof(buf_3), 0)<0) printf("recv_3() failed");   
//...    
send(sock, buf_3, sizeof(buf_3), 0);     
}     
//...   

在第一个send()之后的交换块,有什么想法吗?
udp 是否也支持多个sendto()

感谢您的回答-

【问题讨论】:

  • 如果要异步发送,请使用异步调用。
  • 服务器似乎在 recv() 处阻塞。打印第一个 recv() 得到的内容,并确保代码实际到达服务器中的第一个 send()。
  • 感谢您的回复。在第一个 recv() 之后,它会阻塞。没有错误显示

标签: c++ c sockets network-programming


【解决方案1】:

在这种情况下,send 和 recv 都处于阻塞状态。 您需要在套接字上设置异步标志( O_NONBLOCK 我认为 - 请参阅 fnctl 的文档)。 但这可能很难做到。如果您不发送/获取所有数据,则必须继续调用 send/recv 直到获得所有数据,并且有效地执行此操作意味着您将不得不在套接字上使用 select 系统调用。

现在这一切都相当可行,但调试起来并不有趣和痛苦。 我建议您尝试使用 boost::asio(异步 io)库,而不是使用原始套接字。 http://www.boost.org/doc/libs/1_41_0/doc/html/boost_asio.html

【讨论】:

  • 谢谢!问题不在于异步发送/接收,而是同步
【解决方案2】:

UDP 还是 TCP?

如果是 TCP;您发送的数据有多大。客户在做什么?客户端实际上是在接收和处理第一个数据块吗?可能发生的情况是第二次发送调用被阻塞,因为您的客户端的接收窗口已满,并且 TCP 堆栈已参与流量控制,这导致您的同步发送阻塞等待对等方读取足够的数据,因此接收窗口不是满了,流控情况已经过去了……

还要注意,如果您正在处理 TCP,那么 recv 调用 CAN 并且将返回介于 1 和您已发送的字节数之间的任意字节数;您应该始终循环以累积消息框架告诉您需要的字节数...

您在问题的最后提到了 UDP 和多个 sendTo,这与您的问题有何关系?实际上,您在这里使用 UDP 套接字吗?

【讨论】:

  • 谢谢!此时,我正在使用 TCP,并且在第一个 recv 之后它会阻塞。服务器只接收 buf_1 并停止,而客户端不做任何事情。我还设想在这个应用程序中使用 UDP。
  • 您的问题仍然很模糊,但是如果“服务器”注释之后的代码在第一个 recv 之后阻塞(这是您的建议),那么这完全是可以预期的,因为 recv 将返回尽可能多的字节有可用的。正如我在上面的回复中所说,您需要更好地管理您的 recv 调用;你的代码就这样被破坏了,所有数据都可以被第一个recv读取......
  • 对不起,这个问题不是含糊的,而是技术性的……谢谢你的回答……
  • 不,实际上,它很模糊。例如,您在问题中声明“在第一次发送后阻塞”但您没有说是阻塞的服务器代码路径还是阻塞的客户端代码路径。您的代码示例还显示了一些没有上下文的 if 分支来显示哪个被采用。在您对我的回复的第一条评论中,您声明服务器只收到一个 buf。恕我直言,您提出问题的方式并不是特别精确(或技术性)。不是我不懂技术细节,只是你的提问没有特别具体。
猜你喜欢
  • 2013-02-23
  • 1970-01-01
  • 1970-01-01
  • 2012-06-13
  • 2011-08-19
  • 2023-03-03
  • 2010-11-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多