无法分配请求的地址 - 可能的原因?

Posted

技术标签:

【中文标题】无法分配请求的地址 - 可能的原因?【英文标题】:Cannot assign requested address - possible causes? 【发布时间】:2011-11-30 05:39:25 【问题描述】:

我有一个由主服务器和分布式从服务器组成的程序。从服务器向服务器发送状态更新,如果服务器在固定时间内没有收到特定从服务器的消息,则将该从服务器标记为关闭。这种情况一直在发生。

通过检查日志,我发现从服务器只能向服务器发送一个状态更新,然后永远无法发送另一个更新,总是在调用 connect() 时失败“无法分配请求的地址 ( 99).

奇怪的是,slave 能够向服务器发送其他几个更新,并且所有连接都发生在同一个端口上。似乎导致此故障的最常见原因是连接处于打开状态,但我无法找到任何处于打开状态的东西。还有其他可能的解释吗?

为了澄清,这是我的连接方式:

struct sockaddr *sa; // parameter
size_t           sa_size; //parameter
int              i = 1;
int              stream;

stream = socket(AF_INET,SOCK_STREAM,0);
setsockopt(stream,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(i));
bindresvport(stream,NULL);
connect(stream,sa,sa_size);

此代码位于获取与另一台服务器的连接的函数中,这 4 个调用中的任何一个失败都会导致该函数失败。

【问题讨论】:

我已经验证端口和ip地址都正确。 【参考方案1】:

事实证明,问题确实是地址繁忙 - 繁忙是由我们处理网络通信的其他一些问题引起的。您的意见帮助我解决了这个问题。谢谢。

编辑:具体来说,处理我们的网络通信的问题是,如果第一次失败,这些状态更新将不断重新发送。我们让每个分布式从站尝试同时发送其状态更新只是时间问题,这使我们的网络过度饱和。

【讨论】:

我很想详细说明“忙”,以防它是我自己的代码中出现相同错误的原因——你的意思是“接受连接的服务器等待的套接字队列太长接受()以允许队列中的另一个连接?”还是其他情况?谢谢! @BrandonRhodes 我们的问题是我们在没有适当的退避算法的情况下发生了一些重试,因此我们每秒有数百次或更多次尝试连接到同一个套接字。这种争论导致了我们的失败。实施适当的退避算法对于解决这个问题至关重要。【参考方案2】:

也许 SO_REUSEADDR 在这里有帮助? http://www.unixguide.net/network/socketfaq/4.5.shtml

【讨论】:

为所有连接设置了 SO_REUSEADDR。 这里有一个类似的:***.com/questions/3886506/… @dmh2000 - 我在发布之前查看了该示例,但没有成功尝试调查这些因素。我想知道我是否只需要继续寻找,或者是否有一些我没有考虑到的事情。 你说的那个函数执行了多次吗?在再次调用 connect 之前关闭套接字吗?您能解释一下您的问题中“状态更新”和“其他更新”之间的区别吗?我很困惑为什么你说“...slave 只能发送一个状态更新...”然后“...slave 能够发送几个其他更新...”。 @Michel - 在发送更新并收到收到更新的确认后立即关闭连接。 “其他更新”主要报告服务器要求从属设备执行的任务。从站可以联系服务器进行此类报告,但不能联系其状态更新。它令人困惑。其他更新大多写回从主服务器打开的套接字,对于这些更新,从服务器打开连接。【参考方案3】:

这只是在黑暗中的一个镜头:当你在没有绑定的情况下调用 connect 时,系统会分配你的本地端口,如果你有多个线程连接和断开连接,它可能会尝试分配一个已经在使用的端口。内核源文件 inet_connection_sock.c 提示了这种情况。就像实验一样,先尝试绑定到本地端口,确保每个绑定/连接使用不同的本地端口号。

【讨论】:

抱歉,我发布该代码时并没有查看我的代码。我确实在连接之前调用了绑定。我会更新我的问题以更好地展示我在做什么。【参考方案4】:

好的,我的问题不是端口,而是绑定地址。我的服务器有一个内部地址 (10.0.0.4) 和一个外部地址 (52.175.223.XX)。当我尝试连接时:

$sock = @stream_socket_server('tcp://52.175.223.XX:123', $errNo, $errStr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN);

失败是因为本地套接字是 10.0.0.4 而不是外部 52.175.223.XX。您可以使用sudo ifconfig 查看本地可用接口。

【讨论】:

这为我节省了大量时间 - 谢谢@Dallas Clarke!相同的问题/解决方案适用于 AWS EC2 实例。【参考方案5】:
sysctl -w net.ipv4.tcp_timestamps=1
sysctl -w net.ipv4.tcp_tw_recycle=1

【讨论】:

没有解释这个答案没有任何价值。

以上是关于无法分配请求的地址 - 可能的原因?的主要内容,如果未能解决你的问题,请参考以下文章

针对 localhost 相对 url 的请求“无法分配请求的地址”

Uwsgi:“无法分配请求的地址”

Docker 无法分配请求的地址

nginx 错误:(99:无法分配请求的地址)

JMeter:java.net.NoRouteToHostException:无法分配请求的地址(地址不可用)

Akka,发送Udp失败,“无法分配请求的地址”