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