【问题标题】:Socket Exception: "There are no more endpoints available from the endpoint mapper"套接字异常:“端点映射器没有更多可用的端点”
【发布时间】:2010-09-21 07:31:15
【问题描述】:

我正在使用 winsock 和 C++ 来设置服务器应用程序。我遇到的问题是对listen 的调用导致第一次机会异常。我想通常这些可以忽略(?),但我发现其他人也遇到了与我相同的问题,它导致应用程序每隔一段时间就会挂起。任何帮助将不胜感激。

第一次机会例外是:

MyApp.exe 中 0x*12345678* 处的第一次机会异常:0x000006D9:端点映射器中没有更多可用的端点。

我发现了一些证据表明这可能是由套接字引起的,我正在使用的代码如下。在倒数第五行调用listen 时发生异常。

  m_accept_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

  if (m_accept_fd == INVALID_SOCKET)
  {
    return false;
  }

  int optval = 1;

  if (setsockopt (m_accept_fd, SOL_SOCKET, SO_REUSEADDR,
                  (char*)&optval, sizeof(optval)))
  {
    closesocket(m_accept_fd);
    m_accept_fd = INVALID_SOCKET;
    return false;
  }

  struct sockaddr_in  local_addr;
  local_addr.sin_family = AF_INET;
  local_addr.sin_addr.s_addr = INADDR_ANY;
  local_addr.sin_port = htons(m_port);

  if (bind(m_accept_fd, (struct sockaddr *)&local_addr,
           sizeof(struct sockaddr_in)) == SOCKET_ERROR)
  {
    closesocket(m_accept_fd);
    return false;
  }

  if (listen (m_accept_fd, 5) == SOCKET_ERROR)
  {
    closesocket(m_accept_fd);
    return false;
  }

【问题讨论】:

  • 这个监听是否只在启动时执行?您绑定的端口是动态的吗?您一次监听了多少个端口?

标签: c++ exception sockets winsock rpc


【解决方案1】:

在一个非常繁忙的服务器上,您可能会用完套接字。您可能需要调整一些 TCPIP 参数。在注册表中调整这两个:

HKLM\System\CurrentControlSet\Services\Tcpip\Parameters
   MaxUserPort  REG_DWORD  65534 (decimal)
   TcpTimedWaitDelay REG_DWORD 60 (decimal)

默认情况下,释放网络端口(套接字)和重新使用它之间会有几分钟的延迟。此外,根据操作系统版本,Windows 将使用的范围内只有几千个。在服务器上,在命令提示符下运行:

netstat -an

并查看结果(管道到文件最简单:netstat -an > netstat.txt)。如果您在 Timed Wait Delay 状态下看到 1025->5000 的大量端口,那么这就是您的问题,可以通过使用上面的注册表项将最大用户端口从 5000 调整到 65534 来解决。您还可以通过使用上面的注册表项来调整延迟,以更快地回收端口。

如果这不是问题,那么问题很可能是您在 Listen() 方法中设置的挂起连接数。

【讨论】:

    【解决方案2】:

    原来的问题与winsock无关。以上所有答案都是错误的。忽略第一次机会异常,这不是您的应用程序的问题,只是一些内部错误处理。

    【讨论】:

      【解决方案3】:

      您是否真的看到了问题,例如,程序是否因为未处理的异常而结束?

      即使没有问题,调试器也可能会打印消息,例如,请参阅here

      【讨论】:

        【解决方案4】:

        呃,也许是因为你极大地限制了传入连接的最大数量?

        listen (m_accept_fd, 5)
        // Limit here       ^^^
        

        如果您允许更大的积压,您应该能够处理您的问题。使用 SOMAXCONN 之类的东西而不是 5。

        另外,如果您的问题仅发生在服务器启动时,您可能需要关闭 LINGER (SO_LINGER) 以防止连接挂起并阻塞套接字...

        【讨论】:

        • 更改为 SOMAXCONN 并没有帮助,但这肯定是我会随身携带的一个小窍门。 LINGER 也没有帮助 :-(
        【解决方案5】:

        这不会直接回答您的问题,但由于您使用的是 C++,因此我建议您使用 Boost::Asio 之类的东西来处理您的套接字代码。这为您提供了对 winsock API 的一个很好的抽象,并且应该允许您更轻松地诊断错误情况。

        【讨论】:

          猜你喜欢
          • 2021-10-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-09-03
          • 2013-06-21
          • 1970-01-01
          相关资源
          最近更新 更多