Python套接字没有正确关闭连接

Posted

技术标签:

【中文标题】Python套接字没有正确关闭连接【英文标题】:Python socket doesn't close connection properly 【发布时间】:2011-06-29 18:08:32 【问题描述】:

我是套接字编程的新手,遇到了一个令人费解的问题:

我有一个无法更改的 Windows 程序(专有软件),但它尝试使用 tcp 套接字连接到特定的 IP 和端口。

在我的 linux 机器上,我编写了一个小的 python 脚本来为 win prog 提供套接字。这工作正常,直到我在 linux 上杀死我的 prog。初始服务器套接字未按指定关闭,在套接字被垃圾收集之前我无法重新启动程序。

如果我对 linux 套接字(在单独的 python 脚本中)尝试相同的操作,我没有问题。

这是一个最小的代码示例:

import socket

server = socket.socket()
server.bind(('192.168.0.111', 50001))
server.listen(1)
conn, addr = server.accept()
print 'Connection established'

running = True
while running:
    try:
        data = conn.recv(4096)
    except KeyboardInterrupt:
        conn.close()
        running = False
    else:
        if data:
            print data
        else:
            conn.close()
            running = False
server.close()

如果我用 Ctrl-C 杀死它,它会正常退出。但是在重新启动脚本后,我得到一个 socket.error 说明该地址已在使用中。大约一分钟后,程序再次运行。

我也尝试在关闭前关闭(又名 conn.shutdown(2) 和 server.shutdown...),但没有效果。

有没有更好的“正确”方法来关闭 Windows 套接字?我是否错过了有关套接字的一些基本知识?

谢谢!

编辑:我想我刚刚在这里看到了答案: what is the correct way to close a socket in python 2.6?

虽然我使用的是 python 2.5,但它可能仍然可以工作。

【问题讨论】:

echo "disconnect" | nc 192.168.1.12 58888 -w 1 - 从客户端你可以超时 1 秒,让服务器有自己的超时时间 【参考方案1】:

您正在经历连接套接字的TIME_WAIT 状态。即使您关闭了套接字,它仍然会在几分钟内产生挥之不去的后果。 UNIX guide socket FAQ 中解释了造成这种情况的原因,以及您可以设置以禁用该行为 (SO_REUSEADDR) 的套接字标志。

总之,

server = socket.socket()
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(...)
...

【讨论】:

已连接个套接字的TIME_WAIT状态。 添加了一些上下文【参考方案2】:

尝试添加 import sys 并使用 sys.exit() 终止您的应用。套接字保持保留,直到系统对应用程序关闭感到满意。您可以使用 sys.exit() 明确说明这一点

[编辑]哦,好的。我自己对套接字很陌生。所以你是说这个序列不安全?我无法想象任何其他方式来做到这一点。你必须在某个时候通过一些技巧关闭你的应用程序,对吧?那么它是如何正确完成的呢?

server.shutdown(socket.SHUT_RDWR) 
server.close()
sys.exit()

【讨论】:

我实际上也想到了这一点,并将其写入我的脚本中。如果这对套接字关闭之前的延迟有影响,则可以忽略不计。 我不推荐使用 sys.exit()。您最终可能会遇到挂起的套接字,这在 Unix 上非常罕见,在 Windows 上并不罕见。如果你在 Windows 上挂了一个套接字,你必须重新启动才能修复。 sys.exit() 与退出 Python 进程的任何其他方式没有任何不同。因此,您的建议归结为“如果您创建了任何套接字,请不要退出”,这有点不切实际。如果您的程序永远不会退出,您可能也必须重新启动。 ;) 一般来说,Windows 是相当脆弱的,防火墙和防病毒软件之类的东西会使它更加脆弱。但是,退出一个打开了套接字的进程可能基本上一直都是安全的,如果不是这样,你的系统就会出现很多问题,以至于你不会真正注意到一个有问题的 Python 程序。

以上是关于Python套接字没有正确关闭连接的主要内容,如果未能解决你的问题,请参考以下文章

发送后如何正确关闭套接字(使用 IOCP)?

为啥在从服务器接收到所有数据后客户端套接字连接没有关闭?

远程协助开发总结

python中的广播套接字服务器[关闭]

Python [Errno 98] 地址已在使用中

检测非阻塞套接字上的关闭连接