Python socket未能正确关闭连接

12 投票
2 回答
30105 浏览
提问于 2025-04-16 12:03

我刚接触套接字编程,遇到了一个让人困惑的问题:

我有一个无法修改的Windows程序(是专有软件),它试图通过TCP套接字连接到一个特定的IP和端口。

在我的Linux机器上,我写了一个小的Python脚本来为这个Windows程序提供套接字服务。这一切都运行得很好,直到我在Linux上结束了我的程序。最开始的服务器套接字没有按照预期关闭,我无法重新启动我的程序,直到这个套接字被垃圾回收。

如果我用一个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,提示地址已经在使用中。大约过了一分钟后,程序又可以正常工作了。

我还尝试在关闭之前进行shutdown(比如conn.shutdown(2)和server.shutdown...),但这没有任何效果。

有没有更好的“正确”的方法来关闭Windows套接字?我是不是对套接字的基本概念有什么误解?

谢谢!

补充:我想我刚刚在这里看到了答案:在Python 2.6中关闭套接字的正确方法是什么?

虽然我使用的是Python 2.5,但也许仍然有效。

2 个回答

2

试着添加 import sys,并用 sys.exit() 来结束你的应用程序。这样,系统会知道你的应用已经关闭,直到它确认这个应用真的结束了,那个网络连接才会被释放。用 sys.exit() 可以让这个过程更明确。

[编辑]哦,明白了。我自己对网络连接也很陌生。你是说这个操作顺序不安全?我想不出其他的办法来处理这个问题。总得在某个时候关闭你的应用,用某种方法,对吧?那正确的做法是什么呢?

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

你现在遇到了连接套接字的 TIME_WAIT 状态。即使你已经关闭了套接字,它仍然会在接下来的几分钟内产生一些影响。造成这种情况的原因,以及一个可以设置的套接字标志(SO_REUSEADDR),可以用来禁用这种行为,详细信息可以在UNIX指南的套接字常见问题解答中找到。

简单来说,

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

撰写回答