Python套接字未正确关闭连接。

12

我对 socket 编程不太了解,并遇到一个令人困惑的问题:

我有一个 Windows 程序,但我不能更改它(专有软件),该程序尝试使用 tcp socket 连接到特定的 IP 地址和端口。

在我的 Linux 系统上,我编写了一个小的 Python 脚本来为 win 程序提供 socket 服务。这很好地工作,直到我杀掉 Linux 上的程序。初始服务器套接字没有按照规定关闭,直到套接字被垃圾收集了,我才能重新启动程序。

如果我在单独的 Python 脚本中尝试使用 Linux 套接字,则没有问题。

这是一个最简示例代码:

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,但它可能仍然有效。

从客户端可以进行1秒的超时,并让服务器拥有自己的超时时间。命令为:echo "disconnect" | nc 192.168.1.12 58888 -w 1 - user285594
2个回答

33
你正在经历已连接套接字的TIME_WAIT状态。 即使你关闭了套接字,它仍然会持续几分钟的后果。 有关原因以及可以设置的套接字标志以禁用此行为(SO_REUSEADDR),请参阅UNIX指南套接字FAQ
简而言之,
server = socket.socket()
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(...)
...

已连接套接字的TIME_WAIT状态。 - user207421
未提供上下文,故无法翻译。 - Jean-Paul Calderone

2
尝试添加import sys并使用sys.exit()终止您的应用程序。直到系统确认应用程序已关闭,套接字才会保留。您可以通过sys.exit()明确表示这一点。
[编辑]哦,好的。我自己对套接字非常新。所以你是说这个顺序不安全吗?我无法想象其他方法来做到这一点。您必须使用某种技术在某个时刻关闭应用程序,对吧?那么正确的做法是什么呢?
server.shutdown(socket.SHUT_RDWR) 
server.close()
sys.exit()

我也考虑过这个问题,并在我的脚本中实现了它。如果这对套接字关闭的延迟产生影响,那么它是可以忽略不计的。 - BandGap
我不建议使用sys.exit()。在Unix上很少发生,但在Windows上并不罕见,可能会导致套接字挂起。如果你在Windows上挂起了套接字,则必须重新启动才能解决。 - KaizenSoze
sys.exit()并不比其他Python进程退出方式有任何区别。所以你的建议是“如果你创建了任何套接字,就不要退出”,这有点不切实际。如果你的程序从来不退出,你可能也得重新启动。;) 一般来说,Windows相当不稳定,像防火墙和杀毒软件这样的东西会使它变得更加不稳定。但是,退出具有套接字的进程在大多数情况下基本上是安全的,如果不安全,你的系统将会有很多问题,你不会真正注意到一个有问题的Python程序。 - Jean-Paul Calderone

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接