Python 3 - 带 select.select() 的套接字 - 检测连接丢失
Python 3 - Sockets with select.select() - detecting loss of connection
我有一个 Python 3 服务器脚本,它运行一个 TCP 套接字服务器,使用 select.select()
检测和响应传入数据
我正在使用 select.select() 来处理没有线程的多个连接,并且服务器主要是反应性的(只等待数据并响应数据)。它为另一端设备的每个连接和参数保留一个字典;每个设备的条目在其连接关闭时被删除。
我的问题是我的客户有时会在没有真正关闭 TCP 套接字的情况下失去连接,我不知道如何捕获或创建超时来关闭套接字并从字典中删除旧连接。
有什么好的方法吗?
这是脚本的简化副本:
host = '192.168.0.252'
port = 9989
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((host,port))
server.listen(16)
socks = [server]
devices = {}
while True:
readable,writable,exceptionavailable = select.select(socks,[],[])
for s in readable:
if(s == server):
client, address = server.accept()
socks.append(client)
else:
try: data = s.recv(1024)
except ConnectionResetError: data = 0
if data:
print(data) # Would append device to "devices" dictionary
else:
s.close()
socks.remove(s)
del(devices[did]) # did is the ID that needs deleting from dictionary
如有任何帮助,我们将不胜感激。
编辑: 根据@Daniel 的评论更新了更好的代码。
假设您想关闭一个连接,如果您在 X 秒内没有读取它。那么你必须:
- 对于每个套接字,跟踪您上次读取它的时间。
- 每次select returns更新最后读取时间,关闭超时连接
在此代码中,连接的超时设置为 300 秒。
lastread = {} # a dictionary with sockets as keys
...
readable,_,_ = select.select(socks,[],[], 60)
now = time()
for s in readable:
... read from the socket s and process input ...
lastread[s] = now
closed = []
for s in lastread:
if s not in readable and now - lastread[s] > 300:
... close connection ...
closed.append(s)
for s in closed: del lastread[s]
备注:
- 传递给
select
的超时(在本例中为 60)与连接超时没有太大关系。它只是说您希望最多 60 秒后将控制权交还给您。
- 确保在创建套接字时初始化
lastread[s]
s
并在关闭连接时删除密钥。
更多资源:
我有一个 Python 3 服务器脚本,它运行一个 TCP 套接字服务器,使用 select.select()
检测和响应传入数据我正在使用 select.select() 来处理没有线程的多个连接,并且服务器主要是反应性的(只等待数据并响应数据)。它为另一端设备的每个连接和参数保留一个字典;每个设备的条目在其连接关闭时被删除。
我的问题是我的客户有时会在没有真正关闭 TCP 套接字的情况下失去连接,我不知道如何捕获或创建超时来关闭套接字并从字典中删除旧连接。
有什么好的方法吗?
这是脚本的简化副本:
host = '192.168.0.252'
port = 9989
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((host,port))
server.listen(16)
socks = [server]
devices = {}
while True:
readable,writable,exceptionavailable = select.select(socks,[],[])
for s in readable:
if(s == server):
client, address = server.accept()
socks.append(client)
else:
try: data = s.recv(1024)
except ConnectionResetError: data = 0
if data:
print(data) # Would append device to "devices" dictionary
else:
s.close()
socks.remove(s)
del(devices[did]) # did is the ID that needs deleting from dictionary
如有任何帮助,我们将不胜感激。
编辑: 根据@Daniel 的评论更新了更好的代码。
假设您想关闭一个连接,如果您在 X 秒内没有读取它。那么你必须:
- 对于每个套接字,跟踪您上次读取它的时间。
- 每次select returns更新最后读取时间,关闭超时连接
在此代码中,连接的超时设置为 300 秒。
lastread = {} # a dictionary with sockets as keys
...
readable,_,_ = select.select(socks,[],[], 60)
now = time()
for s in readable:
... read from the socket s and process input ...
lastread[s] = now
closed = []
for s in lastread:
if s not in readable and now - lastread[s] > 300:
... close connection ...
closed.append(s)
for s in closed: del lastread[s]
备注:
- 传递给
select
的超时(在本例中为 60)与连接超时没有太大关系。它只是说您希望最多 60 秒后将控制权交还给您。 - 确保在创建套接字时初始化
lastread[s]
s
并在关闭连接时删除密钥。
更多资源: