为什么IO-multiplexing要与非阻塞IO一起使用

xiaoxiao2021-02-28  145

先看一个例子IO-multiplexing+阻塞IO

首先需要明确的是IO复用是同步的,并不是异步的

IO-multiplexing+阻塞IO

程序实现了Netcat的简单功能

#!/usr/bin/python import os import select import socket import sys def relay(sock): poll = select.poll() poll.register(sock, select.POLLIN) poll.register(sys.stdin, select.POLLIN) done = False while not done: events = poll.poll(10000) # 10 seconds for fileno, event in events: if event & select.POLLIN: if fileno == sock.fileno(): data = sock.recv(8192) if data: sys.stdout.write(data) else: done = True else: assert fileno == sys.stdin.fileno() data = os.read(fileno, 8192) if data: sock.sendall(data) else: sock.shutdown(socket.SHUT_WR) poll.unregister(sys.stdin) def main(argv): if len(argv) < 3: binary = argv[0] print "Usage:\n %s -l port\n %s host port" % (argv[0], argv[0]) return port = int(argv[2]) if argv[1] == "-l": # server server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server_socket.bind(('', port)) server_socket.listen(5) (client_socket, client_address) = server_socket.accept() server_socket.close() relay(client_socket) else: # client sock = socket.create_connection((argv[1], port)) relay(sock) if __name__ == "__main__": main(sys.argv)

试验1

[root@localhost python]# python netcat.py localhost 1234 > /dev/null //chargen会打印吞吐量,write hole,只输出数据,不接受数据 [root@localhost tpc]# ./chargen -l 1234 Accepting... Ctrl-C to exit accepted no. 1 client 171.688 MiB/s 166.395 MiB/s 186.773 MiB/s 240.171 MiB/s 235.967 MiB/s 130.270 MiB/s 18.044 MiB/s client端 python netcat.py localhost 1234 > /dev/null

试验2

先在./chargen -l 1234命令行下敲几个输入,如下 [root@localhost tpc]# ./chargen -l 1234 Accepting... Ctrl-C to exit accepted no. 1 client 171.688 MiB/s 166.395 MiB/s 186.773 MiB/s 240.171 MiB/s 235.967 MiB/s 130.270 MiB/s 18.044 MiB/s accepted no. 2 client 11.838 MiB/s 。。 //这里chargen不打印了,阻塞了 client端 python netcat.py localhost 1234 < /dev/zero > /dev/null

这里用strace看一下netcat.py阻塞在了sendto()上。 用netstat查看下

[root@localhost david]# netstat -tnp | grep 1234 tcp 5966266 4188544 127.0.0.1:50776 127.0.0.1:1234 ESTABLISHED 5620/python tcp 975372 4169984 127.0.0.1:1234 127.0.0.1:50776 ESTABLISHED 5612/./chargen

netcat.py阻塞在了write上,其发送缓冲区满了;因此chargen也会阻塞在write上。

再看一个thread-per-connection的netcat,并没有影响,chargen任然在打印

[root@localhost david]# netstat -tnp | grep 1234 tcp 0 4188544 127.0.0.1:50778 127.0.0.1:1234 ESTABLISHED 5802/./netcat tcp 975372 0 127.0.0.1:1234 127.0.0.1:50778 ESTABLISHED 5612/./chargen

netcat继续再收,虽然阻塞在发送上(可从上面看出netcat的发送缓冲区满了),但是任然在接受。

注意IO复用如果和阻塞IO一起使用了,一旦真的阻塞,就会把此事件循环中管的别的事件挡住了

转载请注明原文地址: https://www.6miu.com/read-66405.html

最新回复(0)