Python:Binding Socket:“地址已在使用中”

2024-04-19 08:06:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个关于TCP/IP网络上的客户端套接字的问题。假设我用

try:

    comSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    comSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

except socket.error, msg:

    sys.stderr.write("[ERROR] %s\n" % msg[1])
    sys.exit(1)

try:
    comSocket.bind(('', 5555))

    comSocket.connect()

except socket.error, msg:

    sys.stderr.write("[ERROR] %s\n" % msg[1])

    sys.exit(2)

创建的套接字将绑定到端口5555。问题是在结束连接之后

comSocket.shutdown(1)
comSocket.close()

使用wireshark,我看到插座被两边的FIN,ACK和ACK关闭,我不能再使用端口了。我得到以下错误:

[ERROR] Address already in use

我想知道怎样才能马上清除端口,以便下次我还能使用同一个端口。

comSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

setsockopt似乎无法解决问题 谢谢您!


Tags: 端口sostderrsysmsgerrorsockettry
3条回答

实际上,sou REUSEADDR标志会导致更大的后果:sou REUSADDR允许您使用一个在等待时间内被阻塞的端口,但是您仍然不能使用该端口建立到它连接到的最后一个地方的连接。什么?假设我选择本地端口1010,连接到foobar.com端口300,然后在本地关闭,让该端口及时等待。我可以立即重用本地端口1010连接到foobar.com端口300以外的任何地方。

但是,通过确保远程端启动关闭(关闭事件),可以完全避免时间等待状态。所以服务器可以通过让客户端先关闭来避免问题。应用程序协议的设计必须使客户端知道何时关闭。服务器可以安全地关闭以响应来自客户端的EOF,但是,如果客户端已不正常地离开网络,则它还需要在预期EOF时设置超时。在许多情况下,仅仅等待几秒钟服务器关闭就足够了。

我还建议你多学习网络和网络编程。你现在至少应该知道tcp协议是如何工作的。这个协议很简单,很小,因此,将来可能会节省很多时间。

使用netstat命令,您可以很容易地看到哪些程序((program_name,pid)元组)绑定到哪些端口以及套接字的当前状态是什么:TIME_WAIT、CLOSING、FIN_WAIT等等。

关于linux网络配置的一个很好的解释可以找到https://serverfault.com/questions/212093/how-to-reduce-number-of-sockets-in-time-wait

在绑定套接字之前,请尝试使用SO_REUSEADDR套接字选项。

comSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

编辑: 我看你还是有麻烦。有一种情况SO_REUSEADDR不起作用。如果尝试绑定套接字并重新连接到相同的目标(启用SO_REUSEADDR),那么TIME_WAIT仍然有效。但是,它将允许您连接到另一个主机:端口。

我想到了几个解决办法。您可以继续重试,直到再次获得连接。或者如果客户机开始关闭套接字(而不是服务器),那么它应该神奇地工作。

这是我测试过的完整代码,绝对没有给出“地址已在使用”错误。您可以将其保存在一个文件中,并从要提供服务的HTML文件的基本目录中运行该文件。另外,可以在启动服务器之前以编程方式更改目录

import socket
import SimpleHTTPServer
import SocketServer
# import os # uncomment if you want to change directories within the program

PORT = 8000

# Absolutely essential!  This ensures that socket resuse is setup BEFORE
# it is bound.  Will avoid the TIME_WAIT issue

class MyTCPServer(SocketServer.TCPServer):
    def server_bind(self):
        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.socket.bind(self.server_address)

Handler = SimpleHTTPServer.SimpleHTTPRequestHandler

httpd = MyTCPServer(("", PORT), Handler)

# os.chdir("/My/Webpages/Live/here.html")

httpd.serve_forever()

# httpd.shutdown() # If you want to programmatically shut off the server

相关问题 更多 >