下面进行一个测试:
- server:chargen.cc,,只发数据不收数据
- client: nc, nc < /dev/zero
chargen 程序只发送数据而不读取,如果使用 nc 时有标准输入,即 nc 会向 chargen 发送数据,将最终导致 chargen 的接收缓冲区被填满,而 nc 无法再发送数据。
因此,nc 的实现方式就显得尤为重要了。如果 nc 这边是网络读写没有分离开,那么由于对端缓冲区满将会导致本端写动作阻塞,进而阻塞整个程序。
示例一:使用系统 nc 与 chargen 测试。可以看到,nc 单向接收时,吞吐量可以达到 1300MiB/s ,而 nc 端有输入时,引起了阻塞。
使用 strace 调试一下程序,发现 nc 阻塞在write上
查看连接上的缓冲区可以发现,由于 chargen 没有读数据,它的输入缓冲区被填满了,导致 nc 阻塞在 write 上,同时由于 write 的阻塞,nc 也不会再读取输入缓冲区的数据。
示例二:使用python实现的 nc 与 chargen 测试。同样的,当 nc 有输入的时候,整个程序就会阻塞。
示例三:使用多线程实现的 nc 与 chargen 测试。可以看到这次即使 nc 有数据输入,程序依然正常运行。
因此,阻塞IO 如果和 IO复用 配合使用,一旦发生阻塞就会影响到同一事件循环下的其他IO事件。