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.x172.16.x.x192.168.x.x127.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】:

当您绑定localhost127.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] 地址已在使用中

socket.error: [Errno 10048]

selenium:socket.error: [Errno 61] 连接被拒绝

Python 处理 socket.error:[Errno 104] 连接由对等方重置

python绑定socket.error:[Errno 13]权限被拒绝