【发布时间】:2020-02-03 16:23:20
【问题描述】:
我在 Python 3.8 中使用 asyncio 库 https://docs.python.org/3/library/asyncio.html
我正在创建一个服务器,在“新接受的连接”回调函数中,我想找出新客户端的远程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 的实例。
这里说的是回调函数。它是类的一部分,因此是主要的 self 论点。
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 的传输类:https://docs.python.org/3/library/asyncio-protocol.html 但也许其他人可以为我指明正确的方向。
Wrt asyncio 的 Transport 类,我可以看到它们允许您通过 get_extra_info(str) 函数查询“额外”信息,例如:
client_r._transport.get_extra_info('socket')
好的,这适用于非加密(非 SSL)流量。但我无法在加密传输中查询套接字。我只能获取 SSL 对象:
https://docs.python.org/3/library/ssl.html#ssl.SSLObject
这个对象提供了一个属性“server_hostname”,它将给我用于连接的主机名/IP,所以此时我只需要端口。
【问题讨论】:
-
如果你也发布你所做的事情(你的代码)会有所帮助。如果您实际显示它,则更容易理解您所说的回调函数。
标签: python python-asyncio