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

dbe*_*eer 22 c sockets tcp errno

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

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

奇怪的是,从服务器能够向服务器发送多个其他更新,并且所有连接都发生在同一端口上.似乎这种失败的最常见原因是连接处于打开状态,但我无法找到任何未解决的问题.还有其他可能的解释吗?

为了澄清,这是我如何连接:

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);
Run Code Online (Sandbox Code Playgroud)

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

Mic*_*hel 9

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

  • 这是一个类似的:http://stackoverflow.com/questions/3886506/why-would-connect-give-eaddrnotavail (2认同)
  • 您所说的那个函数是否执行了多次?再次调用 connect 之前是否关闭套接字?您能否解释一下您的问题中“状态更新”和“其他更新”之间的区别?我很困惑为什么你说“...从站只能发送一个状态更新...”然后“...从站能够发送其他几个更新...”。 (2认同)

dbe*_*eer 7

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

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

  • @BrandonRhodes我们的问题是我们在没有适当的退避算法的情况下进行了一些重试,所以我们每秒都有数百或更多的连接尝试到同一个套接字.这种争论导致了我们的失败.实现适当的退避算法对于解决此问题至关重要. (4认同)
  • 我希望对“忙”进行详细说明,以防它是我自己的代码中出现相同错误的原因 - 您的意思是“接受连接的服务器有太长的套接字队列等待接受()以进行另一个连接”可以排队吗?” 还是其他情况?谢谢! (2认同)

小智 7

好吧,我的问题不是端口,而是绑定地址。我的服务器有一个内部地址(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);
Run Code Online (Sandbox Code Playgroud)

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


dmh*_*000 5

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