Exemplo n.º 1
0
 def data_received(self, data):
     """负责数据的接收、处理和发送,可以会被调用多次"""
     self.data+=data
     if self.data.endswith(b'?'):
         answer = zen_utils.get_answer(self.data)
         self.transport.write(answer)
         self.data = b''
Exemplo n.º 2
0
 def data_received(self, data):
     self.data += data
     if self.data.endswith(b'?'):
         answer = zen_utils.get_answer(self.data)
         #向传输中写入一些数据字节。此方法不会阻塞;它缓冲数据并安排将其异步发送出去。
         self.transport.write(answer)
         self.data = b''
Exemplo n.º 3
0
def serve(listener):
    sockets = {listener.fileno(): listener}
    addresses = {}
    bytes_received = {}
    bytes_to_send = {}

    poll_object = select.poll()
    poll_object.register(listener, select.POLLIN)

    for fd, event in all_events_forever(poll_object):
        sock = socket[fd]

        #Socket closed: remove it from our data structures.

        if event & (select.POLLHUP | select.POLLERR | select.POLLNVAL):
            address = addresses.pop(sock)
            rb = bytes_received.pop(sock, b'')
            sb = bytes_to_send.pop(sock, b'')
            if rb:
                print('Client {} sent {} but then closed'.format(address, rb))
            elif sb:
                print('Client {} closed before we sent {}'.format(address, sb))
            else:
                print('Client {} closed socket normally'.format(address))
            poll_object.unregister(fd)
            del socket[fd]

        # New socket:add it to our data structures.

        elif sock is listener:
            sock, address = sock.accept()
            print('Accepted connection from {}'.format(address))
            sock.setblocking(False)  # force socket.timeout if we blunder
            sockets[sock.fileno()] = sock
            addresses[sock] = address
            poll_object.register(sock, select.POLLIN)

        # Incoming data: keep receiving until we see the suffix.

        elif event & select.POLLIN:
            more_data = sock.recv(4096)
            if not more_data:  # end-of-file
                sock.close()  # next poll() with POLLNVAL, and thus clean up
                continue
            data = byte_received.pop(sock, b'') + more_data
            if data.endwith(b'?'):
                bytes_to_send[sock] = zen_utils.get_answer(data)
                poll_object.modify(sock, select.POLLOUT)
            else:
                bytes_received[sock] = data

        # Socket ready to send: keep sending until all bytes are delivered.

        elif event & select.POLLout:
            data = bytes_to_send.pop(sock)
            n = sock.send(data)
            if n < len(data):
                bytes_to_send[sock] = data[n:]
            else:
                poll_object.modify(sock, select.POLLIN)
Exemplo n.º 4
0
def serve(listener):
    sockets = {listener.fileno(): listener}
    addresses = {}
    bytes_received = {}
    bytes_to_send = {}

    poll_object = select.poll()
    poll_object.register(listener, select.POLLIN)

    for fd, event in all_events_forever(poll_object):
        sock = sockets[fd]

        # Socket closed: remove it from our data structures.

        if event & (select.POLLHUP | select.POLLERR | select.POLLNVAL):
            address = addresses.pop(sock)
            rb = bytes_received.pop(sock, b'')
            sb = bytes_to_send.pop(sock, b'')
            if rb:
                print('Client {} sent {} but then closed'.format(address, rb))
            elif sb:
                print('Client {} closed before we sent {}'.format(address, sb))
            else:
                print('Client {} closed socket normally'.format(address))
            poll_object.unregister(fd)
            del sockets[fd]

        # New socket: add it to our data structures.

        elif sock is listener:
            sock, address = sock.accept()
            print('Accepted connection from {}'.format(address))
            sock.setblocking(False)     # force socket.timeout if we blunder
            sockets[sock.fileno()] = sock
            addresses[sock] = address
            poll_object.register(sock, select.POLLIN)

        # Incoming data: keep receiving until we see the suffix.

        elif event & select.POLLIN:
            more_data = sock.recv(4096)
            if not more_data:  # end-of-file
                sock.close()  # next poll() will POLLNVAL, and thus clean up
                continue
            data = bytes_received.pop(sock, b'') + more_data
            if data.endswith(b'?'):
                bytes_to_send[sock] = zen_utils.get_answer(data)
                poll_object.modify(sock, select.POLLOUT)
            else:
                bytes_received[sock] = data

        # Socket ready to send: keep sending until all bytes are delivered.

        elif event & select.POLLOUT:
            data = bytes_to_send.pop(sock)
            n = sock.send(data)
            if n < len(data):
                bytes_to_send[sock] = data[n:]
            else:
                poll_object.modify(sock, select.POLLIN)
Exemplo n.º 5
0
def serve(listener):
    sockets = {listener.fileno(): listener}  #用监听套接字的文件描述符作为字典的键
    addresses = {}
    bytes_received = {}
    bytes_to_send = {}

    poll_object = select.poll()  #注意:Windows系统只支持select.select()
    poll_object.register(
        listener, select.POLLIN)  #向poll对象注册listener监听套接字,以监视它的【POLLIN事件】

    while True:  #事件监视循环
        for fd, event in poll_object.poll(
        ):  #fd是文件描述符,event是事件掩码;poll()类似selectors模块的sel.select()方法
            sock = sockets[fd]  #先从sockets字典中获得sock套接字对象

            if event & (select.POLLHUP | select.POLLERR | select.POLLNVAL):
                address = addresses.pop(sock)  #从字典中弹出sock键,返回sock键对应的值
                rb = bytes_received.pop(sock, b'')
                sb = bytes_to_send.pop(sock, b'')
                if rb:
                    print('client {} sent {} but then closed'.format(
                        address, rb))
                elif sb:
                    print('client {} closed before we sent {}'.format(
                        address, sb))
                else:
                    print('client {} closed socket normally'.format(address))
                poll_object.unregister(fd)
                del sockets[fd]

            elif sock is listener:  #这段elif块结束后,会不会直接执行下面的select.POLLIN块??因为监听套接字注册的事件就是“select.POLLIN”??但是监听套接字是无法使用下面的sock.recv()方法的??
                sock, address = sock.accept()  #把左边的sock改成conn,以避免歧义??
                print('accepted connection from {}'.format(address))
                sock.setblocking(False)
                sockets[sock.fileno()] = sock  #将连接套接字添加进sockets字典中
                addresses[sock] = address  #将连接套接字的远端地址添加进address字典中
                poll_object.register(
                    sock, select.POLLIN)  #向poll对象注册sock连接套接字,以监视它的【POLLIN事件】

            elif event & select.POLLIN:
                more_data = sock.recv(4096)
                if not more_data:
                    sock.close()
                    continue
                data = bytes_received.pop(sock, b'') + more_data
                if data.endswith(b'?'):
                    bytes_to_send[sock] = zen_utils.get_answer(data)
                    poll_object.modify(sock, select.POLLOUT)
                else:
                    bytes_received[sock] = data

            elif event & select.POLLOUT:
                data = bytes_to_send.pop(sock)
                n = sock.send(data)
                if n < len(data):
                    bytes_to_send[sock] = data[n:]
                else:
                    poll_object.modify(sock, select.POLLIN)
Exemplo n.º 6
0
def server(listener):
    sockets = {
        listener.fileno(): listener
    }  # listener.fileno() 返回一个文件描述符用于底层io操作 文件描述符: 套接字
    addresses = {}
    bytes_received = {}  # 接收缓冲区
    bytes_to_send = {}  # 发送缓冲区

    poll_object = select.poll()  # posix select 返回一个 fd_set 数据结构
    poll_object.register(listener, select.POLLIN)  # 注册监听套接字 默认为 poll input 模式
    for fd, event in all_events_forever(poll_object):
        sock = sockets[fd]
        # socket closed: remove it from our data structures.
        if event & (select.POLLHUP | select.POLLER | select.PLLNVAL):
            address = addresses.pop(sock)
            rb = bytes_received.pop(sock, b'')
            sb = bytes_to_send.pop(sock, b'')
            if rb:
                print("client {} send {} but then closed".format(address, rb))
            elif sb:
                print("client {} closed before we sent {}".format(address, sb))
            else:
                print("clint {} closed socket normally".format(address))
            poll_object.unregister(fd)
            del sockets[fd]
        # new socket: add it to our data structures.
        elif sock is listener:
            sock, address = sock.accept()
            print("accepted connection from {}".format(address))
            sock.setblocking(False)  # force socket.timeout if we blunder
            sockets[sock.fileno()] = sock  # 把套接字文件描述符和套接字本身做字典映射
            addresses[sock] = address  # 把套接字名在字典做映射
            poll_object.register(
                sock, select.POLLIN)  # 在 fd_set 数据结构中注册当前套接字并设定 poll in 状态
        # incoming data: keep receiving until we see the suffix
        elif event & select.POLLIN:
            more_data = sock.recv(4096)
            if not more_data:  # end of file
                sock.close()  # next poll() will POLLNVAL, and thus clean up
                continue
            data = bytes_received.pop(sock, b'') + more_data
            if data.endswith(b'?'):
                bytes_to_send[sock] = zen_utils.get_answer(data)
                poll_object.modify(sock, select.POLLOUT)
            else:
                bytes_received[sock] = data
        # socket ready to send: keep sending until all bytes are delivered.
        elif event & select.POLLOUT:
            data = bytes_to_send.pop(sock)
            n = sock.send(data)
            if n < len(data):
                bytes_to_send[sock] = data[n:]
            else:
                poll_object.modify(sock, select.POLLIN)
Exemplo n.º 7
0
def server(listener):
    sockets = {listener.fileno(): listener}
    address = {}
    bytes_recieved = {}
    bytes_to_send = {}

    poll_object = select.poll()
    poll_object.register(listener, select.POLLIN)

    for fd, event in all_events_forever(poll_object):
        sock = sockets[fd]

        if event & (select.POLLHUP | select.POLLERR | select.POLLNVAL):
            address = address.pop(sock)
            rb = bytes_recieved.pop(sock, b'')
            sb = bytes_to_send(sock, b'')
            if rb:
                print(f"client {address} sent {rb} but then closed")
            elif sb:
                print(f"client {address} closed before we sent {sb}")
            else:
                print(f"client {address} closed normally")
            poll_object.unregister(fd)
            del sockets[fd]

        elif sock is listener:
            sock, address = sock.accept()
            print(f"accept connection from: {address}")
            sock.setblocking(False)
            sockets[sock.fileno()] = sock

            poll_object.register(sock, select.PULLIN)
        elif event & select.POLLIN:
            more_data = sock.recv(4096)
            if not more_data:
                sock.close()
                continue
            data = bytes_recieved.pop(sock, b'') + more_data
            if data.endswith(b"?"):
                bytes_to_send[sock] = zen_utils.get_answer(data)
                poll_object.modify(sock, select.POLLOUT)
            else:
                bytes_recieved[sock] = data
        elif event & select.POLLOUT:
            data = bytes_to_send.pop(sock)
            n = sock.send(data)
            if n < len(data):
                bytes_to_send[sock] = data[n:]
            else:
                poll_object.modify(sock, select.POLLIN)
Exemplo n.º 8
0
def serve(listener):
    sockets = {listener.fileno(): listener}
    addresses = {}
    bytes_received = {}
    bytes_to_send = {}

    poll_object = select.poll()
    poll_object.register(listener, select.POLLIN)

    for fd, event in all_events_forever(poll_object):
        sock = sockets[fd]

        if event & (select.POLLHUP | select.POLLERR | select.POLLNVAL):
            address = addresses.pop(sock)
            rb = bytes_received.pop(sock, b'')
            sb = bytes_to_send.pop(sock, b'')
            if rb:
                print('client {} send {} but then closed'.format(address, rb))
            elif sb:
                print('client {} closed before we sent {}'.format(address, sb))
            else:
                print('client {} closed socket normally'.format(address))
            poll_object.unregister(fd)
            del sockets[fd]

        elif sock is listener:
            sock, address = sock.accept()
            print('accepted connection from {}'.format(address))
            sock.setblocking(False)
            sockets[sock.fileno()] = sock
            addresses[sock] = address
            poll_object.register(sock, select.POLLIN)
        elif event & select.POLLIN:
            more_data = sock.recv(4096)
            if not more_data:
                sock.close()
                continue
            data = bytes_received.pop(sock, b'') + more_data
            if data.endswith(b'?'):
                bytes_to_send[sock] = zen_utils.get_answer(data)
                poll_object.modify(sock, select.POLLOUT)
            else:
                bytes_received[sock] = data
        elif event & select.POLLOUT:
            data = bytes_to_send.pop(sock)
            n = sock.send(data)
            if n < len(data):
                bytes_to_send[sock] = data[n:]
            else:
                poll_object.modify(sock, select.POLLIN)
Exemplo n.º 9
0
async def handle_conversation(reader, writer):
    """负责一个连接套接字的会话"""
    address = writer.get_extra_info(
        'peername')  #获取writer对象的底层连接套接字的远端地址,即发出该次请求的客户端的地址
    print('accepted connection from {}'.format(address))
    while True:  #持续【接收问题,发送答案】的循环,直到客户端关闭连接套接字为止
        try:
            data = await reader.readuntil(b'?')  #从接收缓冲区持续读取字节串,直到遇到【?】为止
        except asyncio.IncompleteReadError:  #如果遇到了EOF信号,即远端关闭了套接字,则退出协程函数
            break
        answer = zen_utils.get_answer(data)
        writer.write(answer)  #将答案写入发送缓冲区
        await writer.drain()  #控制write()方法写入的流量
    print('close the connection')
    writer.close()  #关闭writer底层的服务器连接套接字
def handle_conversation(reader, writer):
    address = writer.get_extra_info('peername')
    print("accepted connection from {}".format(address))
    while True:
        data = b''
        while not data.endswith(b"?"):
            more_data = yield from reader.read(4096)
            if not more_data:
                if data:
                    print("client {} sent {!r} but then closed".format(address, data))
                else:
                    print("client {} closed socket normally".format(address))
                return
            data += more_data
        answer = zen_utils.get_answer(data)
        writer.write(answer)
Exemplo n.º 11
0
def handle_conversation(reader, writer):
    address = writer.get_extra_info('peername')
    print(f"accept connection from:{address}")

    while True:
        data = b''
        while not data.endswith(b"?"):
            more_data = yield from reader.read(4096)
            if not more_data:
                if data:
                    print(f"client :{address} sent {repr(data)} but closed")
                else:
                    print(f"client:{address} closed socket normally")
                return
            data += more_data
        answer = zen_utils.get_answer(data)
        writer.write(answer)
Exemplo n.º 12
0
def handle_conversation(reader, writer):
    address = writer.get_extra_info('peername')
    print('Accepted connection from {}'.format(address))
    while True:
        data = b''
        while not data.endswith(b'?'):
            more_data = yield from reader.read()
            if not more_data:
                if data:
                    print('Client {} sent {!r} but then closed'
                          .format(address, data))
                else:
                    print('Client {} closed socket normally'.format(address))
                return
            data += more_data
        answer = zen_utils.get_answer(data)
        writer.write(answer)
Exemplo n.º 13
0
def handle_conversation(reader, writer):
    address = writer.get_extra_info('peername')
    print('Accepted connection from {}'.format(address))
    while True:
        data = b''
        while not data.endswith(b'?'):
            more_data = yield from reader.read(
                4096)  # 通过yield from来进行中断,因为这里由于接受可能会产生中断
            if not more_data:
                if data:
                    print('Client {} sent {!r} but then closed'.format(
                        address, data))
                else:
                    print('Client {} closed socket normally'.format(address))
                return
            data += more_data
        answer = zen_utils.get_answer(data)
        writer.write(answer)
Exemplo n.º 14
0
 def data_received(self, data):
     self.data += data
     if self.data.endswith(b'?'):
         answer = zen_utils.get_answer(self.data)
         self.transport.write(answer)
         self.data = b''
Exemplo n.º 15
0
 def found_terminator(self):
     answer = zen_utils.get_answer(self.data + b'?')
     self.push(answer)
     self.initiate_send()
     self.data = b''
Exemplo n.º 16
0
 def data_received(self, data):
     self.data += data
     if self.data.endswith(b'?'):
         answer = zen_utils.get_answer(self.data)
         self.transport.write(answer)
         self.data = b''
Exemplo n.º 17
0
def server(listener):
    # 获取已经准备好进行后续通信的文件描述符,并放入字典中以便之后查询
    sockets = {listener.fileno(): listener}  # 获取监听套接字的文件描述符

    addresses = {}  # 用于保存每个与客户端连接的专用套接字

    # 在等待某个请求完成时, 会将收到的数据存储在bytes_received字典中
    bytes_received = {}

    # 在等待OS安排发送数据时,将要发送的字节存储在bytes_to_send字典中
    bytes_to_send = {}

    poll_object = select.poll()
    # select.poll() 返回一个polling对象,支持registering和unregistering file
    # descriptors, 然后 polling them for I/O events.

    poll_object.register(listener, select.POLLIN)
    # (1)准备连接的客户端首先将它自身视作服务器监听套接字的一个事件,要始终将该事件
    # 设为POLLIN(poll in)状态. 接下来见 elif sock is listener:行注释


    for fd, event in all_events_forever(poll_object):
        sock = sockets[fd]

        # Socket closed: remove it from our data structures.

        if event & (select.POLLHUP | select.POLLERR | select.POLLNVAL):
            # (5) 如果客户端套接字返回了错误信息或者是关闭状态,就将该客户端套接字及其
            # 发送缓冲区域接收缓冲区丢弃. 至此,我们至少已经完整地完成了众多可能同时
            # 进行的会话中的一个

            # POLLHUP: hung up 挂起
            # POLLERR: Error condition of some sort 错误条件
            # POLLNVAL: invalid request: descriptor not open 无效请求

            address = addresses.pop(sock)
            rb = bytes_received.pop(sock, b'')
            sb = bytes_to_send.pop(sock, b'')
            if rb:
                print('Client {} sent {} but then closed'.format(address, rb))
            elif sb:
                print('Client {} closed before we sent {}'.format(address, sb))
            else:
                print('Client {} closed socket normally'.format(address))
            poll_object.unregister(fd)
            # 移除文件描述符
            del sockets[fd]

        # New socket: add it to our data structures.

        elif sock is listener:
            # (1) 响应此类事件的方法就是运行accept().将返回的套接字及其地址存储在字典内,
            # 并通过register()方法告知poll()对象,已经准备好从新返回的客户端套接字
            # 接收数据了.
            sock, address = sock.accept()
            print('Accepted connection from {}'.format(address))
            sock.setblocking(False)     # force socket.timeout if we blunder
            sockets[sock.fileno()] = sock
            addresses[sock] = address  # 将服务器分配的用于和客户端连接的套接字
                                       # 关联起来并存储在字典中.
            poll_object.register(sock, select.POLLIN)   # 准备好接收数据

        # Incoming data: keep receiving until we see the suffix

        elif event & select.POLLIN:
            # (2)当套接字本身就是客户端套接字,并且时间类型为POLLIN时,就能使用recv()
            # 方法最多接收4KB数据了.
            more_data = sock.recv(4096)

            # 如果没有收到数据, 表示客户端发送的是 b'',客户端结束连接.那么服务器
            # 也要关闭这个与相应客户端连接的套接字. 然后继续下次循环.
            if not more_data:   # end-of-file
                sock.close()    # next poll() will POLLNVAL , and thus clean up
                continue
            data = bytes_received.pop(sock, b'') + more_data

            # 收到了一个完整的问题,可以处理该客户端请求,并将结果保存到bytes_received
            # 字典中. 然后将套接字的模式从POLLIN 切换到POLLOUT. POLLIN模式表示要接收
            # 更多的数据,而POLLOUT模式则表示在发送缓冲区空闲时立刻通知系统 .
            # POLLOUT mode, where you want to be notified as soon as the
            # outgoing buffers are free because you are now using the socket
            # to send instead of receive.
            if data.endswith(b'?'):
                bytes_to_send[sock] = zen_utils.get_answer(data)
                poll_object.modify(sock, select.POLLOUT)
            else:
                # 如果还没有收到表示帧尾的问号字符,那么就将数据保存到 bytes_received
                # 字典中, 并返回至循环顶部,进行下一个poll()调用.
                bytes_received[sock] = data

        # Socket ready to send: keep sending until all bytes are delivered.

        elif event & select.POLLOUT:
            # (3) The poll() call now notifies you immediately with POLLOUT
            # whenever the outging buffers on the client socket can accept
            # at least one byte, and you respond by attempting a send() of
            # everything you have left to transmit and by keeping only the
            # bytes that  send() could not squeeze into the outgoing buffers.
            data = bytes_to_send.pop(sock)
            n = sock.send(data)
            if n < len(data):
                bytes_to_send[sock] = data[n:]
            else:
                # (4)如果套接字模式为POLLOUT, 并且send()完成了所有数据的发送, 那么
                # 此时就完成了一个完整的请求-响应循环, 因此套接字将模式切换回POLLIN,
                # 用于下一个请求.
                poll_object.modify(sock, select.POLLIN)
def server(listener, certfile):
    #套接字列表,fileno()返回套接字的文件描述符(一个小整数)
    context = zen_utils.ssl_context(certfile, cafile=None)
    listener = context.wrap_socket(listener, server_side=True)
    sockets = {listener.fileno(): listener}
    addresses = {}
    #两个缓冲队列用于接收和发送
    bytes_received = {}
    bytes_to_send = {}
    #返回一个轮询对象,该对象支持注册和注销文件描述符,然后对它们进行轮询以获取I / O事件
    poll_object = select.poll()
    #向轮询对象注册文件描述符,然后用poll()函数检查文件描述符是否具有任何未决的I / O事件,下面是注册监听套接字文件描述符
    poll_object.register(listener, select.POLLIN)

    for fd, event in all_events_forever(poll_object):
        sock = sockets[fd]
        #判断是不是客户端是不是关了或发生了错误或是无效请求
        if event & (select.POLLHUP | select.POLLERR | select.POLLNVAL):
            address = addresses.pop(sock)
            rb = bytes_received.pop(sock, b'')
            sb = bytes_to_send.pop(sock, b'')
            if rb:
                print('客户端{}发送{}但服务器已关闭'.format(address, rb))
            elif sb:
                print('服务器发送{}但客户端{}已关闭'.format(address, sb))
            else:
                print('客户端{}套接字正常关闭'.format(address))
            poll_object.unregister(fd)
            del sockets[fd]
        #如果取出的套接字是监听套接字
        elif sock is listener:
            sock, address = sock.accept()
            print('接受客户端{}连接'.format(address))
            # 在默认认的情况下,TCP套节字处于阻塞模式中。
            # 换句话说,如果没有完成操作,就不把控制权交给程序。
            # 很多情况下,你并不想让程序等待服务器响应或者有异常终止操作,所以设置非阻塞模式。
            sock.setblocking(False)
            #把建立的服务器套接字放入套接字列表中
            sockets[sock.fileno()] = sock
            #把接收到的客户端套接字地址放入地址列表中
            addresses[sock] = address
            #注册该服务器套接字,以供poll()调用
            poll_object.register(sock, select.POLLIN)
        #判断该套接字位掩码event是不是POLLIN
        elif event & select.POLLIN:
            more_data = sock.recv(1024)
            if not more_data:
                sock.close()
                continue
            data = bytes_received.pop(sock, b'') + more_data
            if data.endswith(b','):
                #如果信息传输完成,把数据保存在发送缓冲队列中,并把该套接字事件设为select.POLLOUT输出
                bytes_to_send[sock] = zen_utils.get_answer(data)
                poll_object.modify(sock, select.POLLOUT)
            else:
                #如果只接收了部分数据,把该数据保存到接收缓冲队列中
                bytes_received[sock] = data
        #判断该套接字位掩码event是不是POLLOUT
        elif event & select.POLLOUT:
            #把数据从发送缓冲队列中弹出并发送,并把事件设置为select.POLLIN输入
            data = bytes_to_send.pop(sock)
            n = sock.send(data)
            if n < len(data):
                bytes_to_send[sock] = data[n:]
            else:
                poll_object.modify(sock, select.POLLIN)
Exemplo n.º 19
0
#Asynchronous I/O inside "asyncio" callback methods.

import asyncio, zen_utils

class ZenServer(asyncio.Protocol):
    
    def connection_made(self, transport):
        self.transport = transport
        self.address = transport.get_extra_info('peername')
        self.data = b''
        print('Accepted connection from {}'.format(self.address))

    def data_received(self, data);
        self.data += data
        if self.data.endswith(b'?'):
            answer = zen_utils.get_answer(self.data)
            self.transport.write(answer)
            self.data = b''

    def connection_lost(self, exc):
        if exc:
            print('Client {} error: {}'.format(self.address, exc))
        elif self.data;
            print('Client {} sent {} but then closed'
                  .format(self.address, self.data))
        else:
            print('Client {} closed socket'.format(self.address))

if __name__ == '__main__':
    address = zen_utils.parse_command_line('asyncio server using callbacks')
    loop = asyncio.get_event_loop()