我正在使用winsock和C ++来设置服务器应用程序。我遇到的问题是对listen
的调用会导致第一次机会异常。我猜通常这些可以被忽略(?)但是我发现其他人有同样的问题我在哪里导致应用程序偶尔挂起一次。任何帮助将不胜感激。
第一次机会异常是:
MyApp 中的0x * 12345678 *的第一次机会异常.exe:0x000006D9:端点映射器中没有其他端点可供使用。
我发现一些证据表明这可能是由socket引起的。我正在使用的代码如下所示。在从底部开始的第五行中调用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;
}
答案 0 :(得分:6)
在非常繁忙的服务器上,您可能正在耗尽套接字。您可能需要调整一些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()方法中设置的挂起连接数。
答案 1 :(得分:3)
最初的问题与winsock无关。以上所有答案都是错误的。忽略第一次机会异常,它不是您的应用程序的问题,只是一些内部错误处理。
答案 2 :(得分:2)
您是否确实发现了问题,例如,程序因未处理的异常而结束了吗?
即使没有问题,调试器也可以打印消息,例如,请参阅here。
答案 3 :(得分:1)
呃,也许是因为你极大地限制了传入连接的最大数量?
listen (m_accept_fd, 5)
// Limit here ^^^
如果您允许更多的积压,您应该能够处理您的问题。使用SOMAXCONN而不是5。
此外,如果您的问题仅在服务器启动时出现,您可能需要关闭LINGER(SO_LINGER)以防止连接闲置并阻止套接字...
答案 4 :(得分:0)
这不会直接回答您的问题,但由于您使用的是C ++,我建议使用Boost::Asio之类的东西来处理套接字代码。这为winsock API提供了一个很好的抽象,并且应该允许您更容易地诊断错误条件。