在套接字断开连接后,有没有方法在Python中使用getpeername()?

2024-04-25 01:10:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我有这样一个简单的服务器:

#!/usr/bin/env python2

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('localhost', 50000))
server.listen(5)

# Set TCP Keepalive
server.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
server.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 1)
server.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 3)
server.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 5)

connection, client_address = server.accept()

while True:
    try:
        data = connection.recv(1024)
    except socket.error:
        print "%s dropped out" % (connection.getpeername(),)
        break

    if data:
        print "%s: %s" % (connection.getpeername(), data)
    else:
        print "%s disconnected" % (connection.getpeername(),)
        break

我使用TCP Keepalive来判断客户机是否消失(而不是正确地断开连接)。在

我看到的问题是当一个客户消失了,我发现套接字错误异常,我的print语句尝试使用connection.getpeername(),不再起作用。它抛出一个

^{pr2}$

例外情况。在

在这个简单的例子中,一次只能连接一个客户机,但是对于一次处理多个客户机的更复杂的代码,知道哪个客户机退出可能很有用。在

一旦套接字断开连接,就没有办法知道它以前连接到了哪个端点吗? 为什么connection对象没有在connection.getpeername()中保留客户机的IP/端口信息, 即使在客户断开连接之后?这是因为connection对象可能是可重用的吗?在

我怎样才能使我的代码真正工作,并打印出哪个客户退出了?我是否需要将connection.getpeername()的输出存储在一个变量中,以便以后可以调用它?这意味着如果我有多个 客户机,我需要为列表中的每个客户机存储connection.getpeername()值?在

我知道使用socket是相当低的级别,而且我非常确定使用SocketServer.TCPServer实际上会更容易——我只是想了解其中涉及的低级网络。在


Tags: 代码data客户机客户serversocketconnectiontcp
1条回答
网友
1楼 · 发布于 2024-04-25 01:10:59

不幸的是,这是操作系统接口的一个限制。在已知套接字断开连接后,二进制(C)程序也无法获取对等名称。这是一种不幸的疣。你不能为一个新的连接重复使用这个套接字,所以我想不出为什么不能检索对等名称,但是。。。不可能

第一个想法是使用一个单独的dict,socket对象用作键,通过该对象可以查找相关的客户端地址:

saved_addr = {}
...
connection, client_address = server.accept()
saved_addr[connection] = client_address`
while True:
    try:
        data = connection.recv(1024)
    except socket.error:
        print("{} disconnected".format(saved_addr[connection]))

第二种方法是创建一个单独的类来包装套接字。该类可以保存从accept获取的对等地址,并在需要时将其返回给您。同时,它可以透明地将所有其他操作委托给底层套接字。

演示:

^{pr2}$

相关问题 更多 >