Python socket未能正确关闭连接
我刚接触套接字编程,遇到了一个让人困惑的问题:
我有一个无法修改的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 个回答
试着添加 import sys,并用 sys.exit() 来结束你的应用程序。这样,系统会知道你的应用已经关闭,直到它确认这个应用真的结束了,那个网络连接才会被释放。用 sys.exit() 可以让这个过程更明确。
[编辑]哦,明白了。我自己对网络连接也很陌生。你是说这个操作顺序不安全?我想不出其他的办法来处理这个问题。总得在某个时候关闭你的应用,用某种方法,对吧?那正确的做法是什么呢?
server.shutdown(socket.SHUT_RDWR)
server.close()
sys.exit()
你现在遇到了连接套接字的 TIME_WAIT
状态。即使你已经关闭了套接字,它仍然会在接下来的几分钟内产生一些影响。造成这种情况的原因,以及一个可以设置的套接字标志(SO_REUSEADDR),可以用来禁用这种行为,详细信息可以在UNIX指南的套接字常见问题解答中找到。
简单来说,
server = socket.socket()
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(...)
...