首页 > Python的asyncio模块在create_connection时是不是同步的?

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

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

探究其实现,发现其中调用了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) 
【热门文章】
【热门文章】