Python 套接字错误:地址已被使用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29217502/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Socket error: Address already in use
提问by Andrew Latham
I have a CherryPy script that I frequently run to start a server. Today I was having to start and stop it a few times to fix some bugs in a config file, and I guess the socket didn't close all the way because when I tried to start it up again I got this issue:
我有一个 CherryPy 脚本,我经常运行它来启动服务器。今天我不得不启动和停止它几次以修复配置文件中的一些错误,我猜套接字并没有完全关闭,因为当我再次尝试启动它时,我遇到了这个问题:
[23/Mar/2015:14:08:00] ENGINE Listening for SIGHUP.
[23/Mar/2015:14:08:00] ENGINE Listening for SIGTERM.
[23/Mar/2015:14:08:00] ENGINE Listening for SIGUSR1.
[23/Mar/2015:14:08:00] ENGINE Bus STARTING
CherryPy Checker:
The Application mounted at '' has an empty config.
[23/Mar/2015:14:08:00] ENGINE Started monitor thread 'Autoreloader'.
[23/Mar/2015:14:08:00] ENGINE Started monitor thread '_TimeoutMonitor'.
[23/Mar/2015:14:08:00] ENGINE Error in HTTP server: shutting down
Traceback (most recent call last):
File "/home/andrew/virtualenvs/mikernels/lib/python2.7/site-packages/cherrypy/process/servers.py", line 188, in _start_http_thread
self.httpserver.start()
File "/home/andrew/virtualenvs/mikernels/lib/python2.7/site-packages/cherrypy/wsgiserver/wsgiserver2.py", line 1848, in start
raise socket.error(msg)
error: No socket could be created
I edited CherryPy's wsgiserver2.py to see the details of the socket.error and error.strerror
was
我编辑了 CherryPy 的 wsgiserver2.py 以查看 socket.error 的详细信息并且error.strerror
是
98 (98, 'Address already in use') Address already in use
Meanwhile my socket is constructed as:
同时,我的套接字构造为:
af = 2
socktype = 1
proto = 6
canonname = ''
sa = ('0.0.0.0', 2112)
self.bind(af, socktype, proto)
(that's not exact code but that's what the values are when the error is fired)
(这不是确切的代码,但这就是触发错误时的值)
I checked netstat and didn't see anything listening on port 2112, what could be causing the problem and how can I go about diagnosing it?
我检查了 netstat 并没有看到任何在端口 2112 上侦听的内容,可能是什么导致了问题,我该如何诊断它?
Thanks!
谢谢!
采纳答案by ForceBru
You can try the following
您可以尝试以下操作
from socket import *
sock=socket()
sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
# then bind
From the docs:
从文档:
The SO_REUSEADDR flag tells the kernel to reuse a local socket in TIME_WAIT state, without waiting for its natural timeout to expire.
SO_REUSEADDR 标志告诉内核重用处于 TIME_WAIT 状态的本地套接字,而无需等待其自然超时到期。
Here's the complete explanation:
这是完整的解释:
Running an example several times with too small delay between executions, could lead to this error:
socket.error: [Errno 98] Address already in use
This is because the previous execution has left the socket in a TIME_WAIT state, and can't be immediately reused.
There is a socket flag to set, in order to prevent this, socket.SO_REUSEADDR:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((HOST, PORT))
多次运行示例,两次执行之间的延迟太小,可能会导致此错误:
socket.error: [Errno 98] Address already in use
这是因为之前的执行使套接字处于 TIME_WAIT 状态,不能立即重用。
为了防止这种情况,有一个套接字标志要设置,socket.SO_REUSEADDR:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((HOST, PORT))
回答by Ryan
You could find the process and kill
it by doing:
您可以kill
通过执行以下操作找到该过程:
ps aux | grep python
, finding the process ID, and stopping it manually by doing:
,找到进程 ID,并通过执行以下操作手动停止它:
sudo kill -9 PID
replacing PID with your PID.
用您的 PID 替换 PID。
I often have to do this while testing with Flask/CherryPy. Would be interested to see if there's an easier way (for e.g. to prevent it in the first place)
在使用 Flask/CherryPy 进行测试时,我经常不得不这样做。有兴趣看看是否有更简单的方法(例如首先防止它)
回答by Lord Salforis
Much more easier to do it by:
Check the PID(:5000 is the host since I've been running on 127.0.0.1:5000):$ lsof -i :5000
Then kill it:$ sudo kill -9 PID
通过以下方式更容易做到:
检查PID(:5000是主机,因为我一直在127.0.0.1:5000上运行):$ lsof -i :5000
然后杀死它:$ sudo kill -9 PID