socket.error:[errno 99] 无法在 python 中分配请求的地址和命名空间
Posted
技术标签:
【中文标题】socket.error:[errno 99] 无法在 python 中分配请求的地址和命名空间【英文标题】:socket.error:[errno 99] cannot assign requested address and namespace in python 【发布时间】:2013-10-15 06:45:33 【问题描述】:我的服务器软件显示errno99: cannot assign requested address
,同时使用127.0.0.1
以外的IP 地址进行绑定。
但是如果 IP 地址是 127.0.0.1
它可以工作。
和命名空间有关吗?
我正在通过调用execfile()
在另一个python 程序中执行我的服务器和客户端代码。
我实际上正在编辑 mininet 源代码。我编辑了 net.py,在里面我使用了 execfile('server.py') execfile('client1.py') 和 execfile('client2.py')。所以只要“ sudo mn --topo single,3" 在创建 3 个主机的同时被调用,我的服务器和客户端代码将被执行。我在下面给出了我的服务器和客户端代码。
#server code
import select
import socket
import sys
backlog = 5
size = 1024
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("10.0.0.1",9999))
server.listen(backlog)
input = [server]
running = 1
while running:
inputready,outputready,exceptready = select.select(input,[],[])
for s in inputready:
if s == server:
client, address = server.accept()
input.append(client)
else:
l = s.recv(1024)
sys.stdout.write(l)
server.close()
#client code
import socket
import select
import sys
import time
while(1) :
s,addr=server1.accept()
data=int(s.recv(4))
s = socket.socket()
s.connect(("10.0.0.1",9999))
while (1):
f=open ("hello1.txt", "rb")
l = f.read(1024)
s.send(l)
l = f.read(1024)
time.sleep(5)
s.close()
【问题讨论】:
向我们展示一些代码,否则我们无法帮助您。 (最好是如何设置套接字,以及如何通过调用execfile()
执行“服务器”(顺便说一句,使用execfile()
的任何原因?))
当您尝试 127.0.0.1 以外的其他地址时,您使用的是哪个地址?我通过绑定到某些无效 IP 重现了您的错误。记住一个服务器只能绑定自己,所以你给的IP或者名字必须是服务器之一...
当您绑定()时,您将套接字与本地 IP 地址和端口相关联。所以,只要地址是本地的,包括 127.0.0.1(本地地址),绑定就可以工作。但是,尝试绑定到非本地地址会导致上述错误。
@Torxed 我已经编辑了问题。请仔细阅读。
@user2833462 10.x.x.x
、172.16.x.x
、192.168.x.x
或 127.0.0.x
是本地网络。但可悲的是,83.127.224.44
是一个本地 address (并且它是您要绑定到的本地 address),因为它是分配给您计算机的地址。 (即,您无法将 bind()
发送到“www.google.com”,因为您不拥有它,但如果您拥有“www.made-up-example.com”,则可以绑定到那个地址,一旦你理解了这个基本概念,你就需要绑定到 made-up-example.com 的 IP 而不是地址本身)。
【参考方案1】:
将事情简化为基础,这就是您想要测试的内容:
import socket
server = socket.socket()
server.bind(("10.0.0.1", 6677))
server.listen(4)
client_socket, client_address = server.accept()
print(client_address, "has connected")
while True:
recvieved_data = client_socket.recv(1024)
print(recvieved_data)
这可以假设一些事情:
-
您的本地 IP 地址(在服务器上)是 10.0.0.1 (This video shows you how)
没有其他软件正在侦听端口 6677
还要注意IP地址的基本概念:
尝试以下操作,打开开始菜单,在“搜索”字段中输入cmd
,然后按回车。
一旦黑色控制台打开,输入ping www.google.com
,这应该会给你和谷歌的IP地址。这个地址是 google 的本地 IP,他们绑定到该地址,显然您可以不绑定到 google 拥有的 IP 地址。
考虑到这一点,您拥有自己的一组 IP 地址。
首先你有服务器的本地 IP,然后你有你家的本地 IP。
下图中192.168.1.50
是可以绑定的服务器的本地IP。
你仍然拥有83.55.102.40
,但问题是它属于路由器而不是你的服务器。因此,即使您访问 http://whatsmyip.com 并告诉您您的 IP 是 83.55.102.40
也并非如此,因为它只能看到您来自哪里......并且您正在从路由器访问您的互联网。
为了让您的朋友访问您的服务器(绑定到192.168.1.50
),您需要将端口6677
转发到192.168.1.50
,这是在您的路由器中完成的。
假设你落后于一个。
如果您在学校,则很可能会遇到其他困境和路由器。
【讨论】:
感谢您对此的解释。如果您使用的是云服务器,这将如何改变。让我们说来自 AWS? @GabrielFair 不确定,因为我不使用云服务。我总是使用可以控制硬件的自托管服务器 :) 在这种情况下,最简单的解决方法是只执行server.bind(("", 6677))
,因为这将绑定到端口 6677 上的所有可用接口 - 而不是将自己限制为已知 IP .我知道 AWS 通常会在外部更改 IP,但在内部它们应该保持不变。您也可以使用其中之一:***.com/questions/270745/…
如何检查是否没有其他软件正在监听所选端口?
@NaveenKumar 取决于您的操作系统。例如ss -lp | grep 6677
。
@Torxed 我正在使用 Ubuntu $ ss -lp | grep 6010 tcp LISTEN 0 128 127.0.0.1:6010 0.0.0.0:* tcp LISTEN 0 128 [::1]:6010
[::]:*【参考方案2】:
如果您尝试从 Docker 容器内连接到公开的端口,而此时没有任何服务正在为该端口提供服务,也会出现此错误。
在没有任何东西监听/绑定到该端口的主机上,当向未提供服务的本地 URL 发出请求时,您会收到 No connection could be made because the target machine actively refused it
错误,例如:localhost:5000
。但是,如果您启动一个绑定到该端口的容器,但其中没有运行实际为该端口提供服务的服务器,则对 localhost 上该端口的任何请求都将导致:
[Errno 99] Cannot assign requested address
(如果从容器内调用),或
[Errno 0] Error
(如果从容器外部调用)。
您可以重现此错误和上述行为,如下所示:
启动一个虚拟容器(注意:如果在本地找不到,这将拉取 python 图像):
docker run --name serv1 -p 5000:5000 -dit python
然后对于 [Errno 0] Error
在主机上输入 Python 控制台,而对于 [Errno 99] Cannot assign requested address
通过调用访问容器上的 Python 控制台:
docker exec -it -u 0 serv1 python
然后在任何一种情况下调用:
import urllib.request
urllib.request.urlopen('https://localhost:5000')
我最终将这些错误中的任何一个视为等同于No connection could be made because the target machine actively refused it
,而不是试图解决它们的原因 - 尽管如果这是一个坏主意,请告知。
考虑到我可以在[Errno 99] Cannot assign requested address
上找到的所有资源和答案都指向binding to an occupied port、connecting to an invalid IP、sysctl
conflicts、@ 987654324@、TIME_WAIT
being incorrect 等等。因此,我想在此处留下这个答案,尽管这不是手头问题的直接答案,因为它可能是导致此问题中描述的错误的常见原因。
【讨论】:
好好挖掘!谢谢! 2020 年仍会发生 太棒了,这是一个足智多谋的东西,节省了很多谷歌浏览......谢谢 很好的观察,感谢分享。当我在同样的情况下第一次看到 os error 99 时,真的很可怕。虽然,我仍然很感兴趣,为什么会发生这种情况?这似乎与 Docker 运行时如何从容器内保留/路由暴露的端口有关,但我很高兴知道真正的实现细节。【参考方案3】:试试这样:
server.bind(("0.0.0.0", 6677))
【讨论】:
这真的有效!你能解释一下为什么我可以使用这个 IP 地址吗?谢谢!【参考方案4】:当您绑定localhost
或127.0.0.1
时,这意味着您可以仅从本地连接到您的服务。
你不能绑定10.0.0.1
,因为它不属于你,你只能绑定你电脑拥有的ip
您可以绑定0.0.0.0
,因为这意味着您计算机上的所有 ip,因此任何 ip 都可以连接到您的服务,如果他们可以连接到您的任何 ip
【讨论】:
【参考方案5】:这不是直接回答问题,而是在上述解决方案失败的情况下调试方向。 当您不在本地环境中时,假设您在 VM 或 WSL 上,由于 NAT,内部网络可能对外部计算机不透明。因此,请确保您可以从尝试绑定的任何位置 ping IP。如果不是,则考虑切换到正确的环境或考虑网络桥接。 如果您正在寻找 WSL2 特定的解决方案,您可以试试这个链接: Bridging WSL2 network adapter with Windows 在 Virtual Box 中,您可以更改 Network Adapter -> Attached To: Bridged Adapter。 另一个考虑因素是,如果您尝试绑定到端口
【讨论】:
以上是关于socket.error:[errno 99] 无法在 python 中分配请求的地址和命名空间的主要内容,如果未能解决你的问题,请参考以下文章
造成socket.error: [Errno 99] Cannot assign requested
socket.error: [Errno 48] 地址已在使用中
selenium:socket.error: [Errno 61] 连接被拒绝