为什么bind()有时会在其他端连接时给出EADDRINUSE?

时间:2012-04-30 13:33:44

标签: c++ sockets udp bind

在我的C ++应用程序中,我使用:: bind()作为UDP套接字,但在极少数情况下,由于连接丢失而重新连接后,即使经过多次重试,我也会得到错误的EADDRINUSE。 UDP连接的另一端将接收重新连接好的数据,并等待select()表示有东西要读。

我认为这意味着本地端口正在使用中。如果是的话,我怎么可能泄漏本地端口,使另一端连接到它?这里真正的问题是另一方连接正常并且正在等待,但这一方仍然停留在EADDRINUSE上。

- 编辑 -

这是一个代码片段,显示我已在TCP套接字上执行SO_REUSEADDR,而不是在我遇到问题的UDP套接字上:

// According to "Linux Socket Programming by Example" p. 319, we must call
// setsockopt w/ SO_REUSEADDR option BEFORE calling bind.
// Make the address is reuseable so we don't get the nasty message.
int so_reuseaddr = 1; // Enabled.
int reuseAddrResult
  = ::setsockopt(getTCPSocket(), SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr,
                 sizeof(so_reuseaddr));

这是完成后关闭UDP套接字的代码:

void
disconnectUDP()
{
  if (::shutdown(getUDPSocket(), 2) < 0) {
    clog << "Warning: error during shutdown of data socket("
         << getUDPSocket() << "): " << strerror(errno) << '\n';
  }
  if (::close(getUDPSocket()) < 0 && !seenWarn) {
    clog << "Warning: error while closing data socket("
         << getUDPSocket() << "): " << strerror(errno) << '\n';

  }
}

2 个答案:

答案 0 :(得分:4)

是的,这是正常的。您需要在绑定之前设置套接字SO_REUSEADDR,例如在* nix:

int sock = socket(...);

int yes = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));

如果您有通过创建新套接字重新连接的单独代码,请将其设置在该套接字上。这与操作系统的默认行为有关 - 断开的套接字上的端口会保持一段时间不存在。

[EDIT]这不应该适用于UDP连接。也许您应该发布用于设置套接字的代码。

答案 1 :(得分:2)

在UDP中没有丢失连接的东西,因为没有连接。您可以丢失已发送的数据包,这就是全部。

不要重新连接,只需重复使用现有的fd