点对点epoll客户端和死锁

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了点对点epoll客户端和死锁相关的知识,希望对你有一定的参考价值。

假设一个点对点程序使用epoll来执行异步TCP读取和写入多个对等点。当然,这意味着每个文件描述符都设置为非阻塞,以允许调用epoll_wait并检查多个套接字。

但是,存在潜在的问题。假设有两个对等体:A和B.A尝试向B写入消息,但B是拥塞或其他东西,因此对write的调用返回-1,errno设置为EAGAIN。此时,A在打电话给epoll_wait时入睡。

但请注意,B已经停止了对epoll_wait的调用。如果B从未收到有关A未能尝试向其发送消息的通知,则B将永远不会唤醒并尝试在A的套接字上执行读取,并且整个事情将会死锁。所以我的问题是,B保证会被通知A正试图向它发送消息,即使A放弃原来的write呼叫并进入睡眠状态?

即使上面的答案是“是”,由于应用层失步,这样的系统是否有可能无限期地死锁?即A试图写入B但失败,所以它进入睡眠状态。然后B醒来并试图从A读取,但因为A进入睡眠而失败。等等

答案

任何具有可能状态的协议都允许双方在读取之前等待另一方读取,这将是一个根本破坏的协议。对于对等协议,通常禁止每一端因为无法写入而延迟读取。

在实现方面,通常每次调用epoll_wait(或发现就绪I / O的等效方式)都会检查程序正在使用的所有描述符的输入。除非应用程序具有已读取的未处理数据,否则读取永远不会延迟,并且只要处理完数据就会停止延迟。在阅读之前等待网络活动通常是一个非常糟糕的主意。

这就是典型的协议中立TCP代理使用两个进程或两个线程的原因。你不能只是从A读取然后对B进行阻塞写入,因为你不知道B在写入之前是否需要读取。

这也是为什么用recv调用MSG_WAITALL几乎总是一个坏主意。另一端可能正在等待您在发送之前接收已发送的字节。没有协议可以允许一方在读取任何字节之前等待所有字节发送,如果它还允许另一方等待直到发送其余字节之前已经读取了一些字节!

以上是关于点对点epoll客户端和死锁的主要内容,如果未能解决你的问题,请参考以下文章

Syncthing – 带版本控制的点对点文件同步工具

移动应用程序和电脑浏览器之间的点对点通信

套接字点对点

用于点对点通信的 Java“对等”套接字

java 通过TCPUDP 协议实现多人聊天,点对点,文件传送-----分服务器端和客户端

点对点语音呼叫 Twilio