您好,我有一个脚本可以保存我设备的池端口状态,这是简化版。
当连接成功(设备存在)时,我关闭连接,连接状态变为 TIME_WAIT。按时此连接起球并达到操作系统允许的最大连接数(如果我没记错的话)
不知道我应该修复哪一部分,例如我使用端口 53,但在实际应用程序上我检查多个端口,如 ssh、vnc 等。
我使用 python 3.5.6 在 ubuntu 18.04 上运行脚本
import asyncio
import ipaddress
import sys
async def check_port(ip, port, timeout=1):
conn = None
response = False
writer = None
try:
conn = asyncio.open_connection(ip, port)
reader, writer = await asyncio.wait_for(conn, timeout=timeout)
response = True
except asyncio.CancelledError:
print("asyncio cancel")
except:
response = False
finally:
if writer is not None:
writer.close()
if conn is not None:
conn.close()
print("Closing connection {}:{}".format(ip, port))
print("{}:{} {}".format(ip, port, response))
async def poll_status():
ips = [str(ip) for ip in ipaddress.IPv4Network("192.168.1.0/24")]
while True:
try:
tasks = [check_port(ip, 53) for ip in ips]
await asyncio.wait(tasks)
except asyncio.CancelledError:
break
except KeyboardInterrupt:
break
except:
pass
await asyncio.sleep(1)
async def shutdown(task):
task.cancel()
await task
await asyncio.sleep(1)
if __name__ == "__main__":
loop = asyncio.get_event_loop()
task = asyncio.ensure_future(poll_status())
try:
loop.run_forever()
except:
pass
finally:
loop.run_until_complete(asyncio.wait([shutdown(task)]))
loop.close()
连接一直像这样堆积(来自“netstat -nput | grep TIME_WAIT”的输出) 192.168.1.1 是我的路由器,所以它在检查端口时成功但留下了很多未关闭的连接。删除连接需要很长时间
tcp 0 0 192.168.1.4:42102 192.168.1.1:53 TIME_WAIT -
tcp 0 0 192.168.1.4:42582 192.168.1.1:53 TIME_WAIT -
tcp 0 0 192.168.1.4:46560 192.168.1.1:53 TIME_WAIT -
tcp 0 0 192.168.1.4:39428 192.168.1.1:53 TIME_WAIT -
tcp 0 0 192.168.1.4:45806 192.168.1.1:53 TIME_WAIT -
tcp 0 0 192.168.1.4:44752 192.168.1.1:53 TIME_WAIT -
tcp 0 0 192.168.1.4:40726 192.168.1.1:53 TIME_WAIT -
tcp 0 0 192.168.1.4:49864 192.168.1.1:53 TIME_WAIT -
tcp 0 0 192.168.1.4:38812 192.168.1.1:53 TIME_WAIT -
tcp 0 0 192.168.1.4:48464 192.168.1.1:53 TIME_WAIT -
tcp 0 0 192.168.1.4:41372 192.168.1.1:53 TIME_WAIT -
tcp 0 0 192.168.1.4:43408 192.168.1.1:53 TIME_WAIT -
tcp 0 0 192.168.1.4:47360 192.168.1.1:53 TIME_WAIT -
tcp 0 0 192.168.1.4:45478 192.168.1.1:53 TIME_WAIT -
tcp 0 0 192.168.1.4:41904 192.168.1.1:53 TIME_WAIT -
tcp 0 0 192.168.1.4:40160 192.168.1.1:53 TIME_WAIT -
tcp 0 0 192.168.1.4:46196 192.168.1.1:53 TIME_WAIT -
tcp 0 0 192.168.1.4:48744 192.168.1.1:53 TIME_WAIT -
tcp 0 0 192.168.1.4:49554 192.168.1.1:53 TIME_WAIT -
tcp 0 0 192.168.1.4:47774 192.168.1.1:53 TIME_WAIT -
tcp 0 0 192.168.1.4:39370 192.168.1.1:53 TIME_WAIT -
tcp 0 0 192.168.1.4:43994 192.168.1.1:53 TIME_WAIT -
最佳答案
我不是网络方面的专家,不确定这个答案是否有帮助,但这是我的两分钱。
关于 netstat 输出的第一件事。它与路由器相关,似乎与您的操作系统限制无关。快速谷歌搜索 shows以下:
TIME_WAIT indicates that local endpoint (this side) has closed the connection. The connection is being kept around so that any delayed packets can be matched to the connection and handled appropriately. The connections will be removed when they time out within four minutes.
似乎是您的代码关闭了连接,即一切正常。
但是我不知道路由器将如何处理越来越多的此类连接。
现在让我们考虑您的代码。
您在 asyncio.wait(tasks)
行所做的是并行运行所有检查。根据 ips
的数量,它可能太多了。您很有可能会受益于使用 asyncio.Semaphore限制并行检查的最大数量。它看起来如下:
sem = asyncio.Semaphore(100)
async def check_port(ip, port, timeout=1):
async with sem:
# main code here
您还可以阅读 this answer查看使用信号量的真实示例。
接下来您可能需要修复的是如何处理 CancelledError
:
except asyncio.CancelledError:
print("asyncio cancel")
这不是任务应对此异常使用react的方式。它永远不应该压制它,只有外部代码可以做到。阅读this answer看看怎么做。
except:
response = False
你永远不会做这样的事情。请阅读this topic了解详情。
您至少应该执行以下操作:
except Exception as exc: # catch Exception or it's subclasses only
logging.exception(exc) # log for purpose not to miss exception you can fix
response = False
关于python-3.x - Asyncio 关闭连接使连接处于 TIME_WAIT 状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55063606/