Python协程同步问题求助asyncio模块,pythonasyncio,在Windows下使用a


在Windows下使用asyncio模块(事件循环用的是默认的_WindowsSelectorEventLoop)

asyncio模块在create_connection时是不是同步的?

探究其BaseEventLoop.create_connection的调用层次,发现其中还同步调用了connect和select函数。

首先,调用层次如下:

BaseEventLoop.create_connection  BaseSelectorEventLoop.sock_connect    BaseSelectorEventLoop._sock_connect      socket.connect

然后参考socket.connect的实现,发现其中调用了connect后,还调用了select。

问题是,本来在程序等待三次握手的时候,Python可以把执行别的协程的,但是这样同步的调用,使得Python只能等待三次握手了。

这样会造成性能问题吗?

如果在异步上下文中调用了阻塞函数,确实会造成性能问题。不过呢,这里的 socket.connect 是非阻塞的,所以不会有性能问题。见 asyncio/base_events.py 393 行:

                    sock = socket.socket(family=family, type=type, proto=proto)                    sock.setblocking(False)

这里设置了 socket 对象为非阻塞的,所以你看到的下面这些代码都会立即返回:

    res = connect(s->sock_fd, addr, addrlen);  // <<<<<<<< 1#ifdef MS_WINDOWS    if (s->sock_timeout > 0.0) {        if (res < 0 && WSAGetLastError() == WSAEWOULDBLOCK &&            IS_SELECTABLE(s)) {            /* This is a mess.  Best solution: trust select */            fd_set fds;            fd_set fds_exc;            struct timeval tv;            tv.tv_sec = (int)s->sock_timeout;            tv.tv_usec = (int)((s->sock_timeout - tv.tv_sec) * 1e6);            FD_ZERO(&fds);            FD_SET(s->sock_fd, &fds);            FD_ZERO(&fds_exc);            FD_SET(s->sock_fd, &fds_exc);            res = select(Py_SAFE_DOWNCAST(s->sock_fd+1, SOCKET_T, int),                         NULL, &fds, &fds_exc, &tv);  // <<<<<<<< 2            if (res == 0) {                res = WSAEWOULDBLOCK;  // <<<<<<<<<< 3                timeout = 1;            } else if (res > 0) {

——即使三次握手还没有完成。异步等待握手完成的代码见 asyncio/selector_events.py 的 308 行:

        except (BlockingIOError, InterruptedError):             self.add_writer(fd, self._sock_connect, fut, True, sock, address) 

编橙之家文章,

评论关闭