如何在Python异步IO服务器中获取新接受的连接的IP地址和端口?

如何在Python异步IO服务器中获取新接受的连接的IP地址和端口?,python,python-asyncio,Python,Python Asyncio,我正在使用Python 3.8中的asyncio库 我正在创建一个服务器,在“新接受的连接”回调函数中,我想找出新客户端的远程IP地址和端口 回调函数的参数是StreamReader和StreamWriter各自的一个实例,用于从客户端进行读写。有没有一种简单的方法可以找到流的IP地址和端口?注意,我希望对SSL和非SSL连接都这样做 我在这里创建服务器: async def create_server(self, new_client_cb, host, port): srvsock

我正在使用Python 3.8中的asyncio库

我正在创建一个服务器,在“新接受的连接”回调函数中,我想找出新客户端的远程IP地址和端口

回调函数的参数是StreamReader和StreamWriter各自的一个实例,用于从客户端进行读写。有没有一种简单的方法可以找到流的IP地址和端口?注意,我希望对SSL和非SSL连接都这样做

我在这里创建服务器:

async def create_server(self, new_client_cb, host, port):
    srvsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    srvsocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    srvsocket.bind((host, port))
    srvsocket.listen(5)
    return await asyncio.start_server(new_client_cb, sock=srvsocket, start_serving=False)
我传入回调函数,它遵循文档并接受StreamReader和StreamWriter的实例

这里说的是回调函数。它是一个类的一部分,因此是主要的自我论证

async def _new_client(self, client_r, client_w):
    try:
        self.logger.debug("New client on incoming proxy")
        dests_r = {}
        dests_w = {}
        for addr in self.config['addrlist']:
            host, port = addr.split(':')
            host = socket.gethostbyname(host)
            self.logger.debug(f"Connecting to {addr}...")
            r, w = await self.protocol.open_connection(host, port)
            self.logger.debug(f"Connected to {addr}")
            dests_r[addr] = r
            dests_w[addr] = w
        done, pending = await asyncio.wait(
            [self._tunnel(list(dests_r.values()), [client_w]), self._tunnel([client_r], list(dests_w.values()))],
            return_when=asyncio.FIRST_EXCEPTION
        )
        for result in done:
            if result.exception():
                raise result.exception()
    except Exception as e:
        self.logger.error(f"Caught exception: {str(e)}")
        traceback.print_exc()
这个函数中有很多内容与我的工作的其他方面有关 应用 我想我的问题最终归结为:在给定这些输入、StreamReader和StreamWriter的情况下,如何找到与新客户机关联的远程地址和端口?我正在研究asyncio的传输类: 但也许其他人能给我指出正确的方向

Wrt asyncio的传输类,我可以看到它们允许您通过get_extra_info(str)函数查询“额外”信息,例如:

client_r._transport.get_extra_info('socket')
好的,这适用于非加密(非SSL)流量。但我无法查询加密传输上的套接字。我只能获取SSL对象:


这个对象提供了一个属性“server\u hostname”,它将为我提供用于连接的主机名/IP,因此此时我只需要端口。

好的,我最终能够找到它

我真的需要传递一个不同的密钥来获取额外的信息

SSL和非SSL传输都支持“peername”密钥

因此,我将代码修改为以下内容:

client_r._transport.get_extra_info('peername')
client_w._transport.get_extra_info('peername')

我遇到的另一个问题是,我在关闭流后查询“peername”键,因此没有得到任何回复。

如果您也发布您所做的事情(您的代码),这会有所帮助。如果您实际显示回调函数,则更容易理解您所指的回调函数。您应该调用
client\w.get\u extra\u info('peername')
。流上的
\u transport
属性是私有的,可以随时删除或重命名(或更改含义)。在文档中,你说得有道理。但是,我还想从StreamReaders读取peername,它不像StreamWriters那样提供get_extra_info方法。坦率地说,我认为这是对API的一种疏忽,读者和作家同时被交代;我想您可以从编写器中提取peername并将其传递给需要它的代码。