4

我在 Windows 2008x64 上的一个 C++ 应用程序有问题(同一个应用程序在 Windows 2003x64 上运行得很好)。

在崩溃之后,甚至有时在定期关闭/重启周期之后,它在使用端口 82 上的套接字时遇到问题,它需要接收命令。

查看 netstat 我看到套接字在应用程序停止超过 10 分钟后仍处于侦听状态(该进程肯定不再运行)。

  TCP    0.0.0.0:82             LISTENING

我尝试将套接字选项设置为 REUSEADDR 但据我所知,这只影响重新连接到处于 TIME_WAIT 状态的端口。无论哪种方式,这种变化似乎都没有任何区别。

int doReuse = 1;
setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR,
           (const char *)&doReuse, sizeof(doReuse)); 

有什么想法可以解决或至少避免这个问题吗?

编辑:

做了 netstat -an 但这就是我得到的全部:

  TCP    0.0.0.0:82             0.0.0.0:0              LISTENING

对于 netstat -anb 我得到:

  TCP    0.0.0.0:82             0.0.0.0:0              LISTENING
 [System]

我知道正常关闭,但即使应用程序由于某种原因崩溃,我仍然需要能够重新启动它。有问题的应用程序使用内部使用 Windows 套接字 API 的内部库。

编辑:

显然这个问题没有解决方案,所以为了开发,我将使用代理/工具来解决它。感谢所有的建议,非常感谢。

4

6 回答 6

2

如果这只是在调试时伤害您,请使用sysinternals 人员的tcpview强制关闭套接字。我假设它适用于您的平台,但我不确定。

如果您在任何套接字上执行阻塞操作,请不要使用无限期超时。根据我的经验,这可能会在多处理器机器上导致奇怪的行为。我不确定它是什么 Windows 服务器操作系统,但它是 2003 Server 之前的一两个版本。不要无限期超时,而是使用 30 到 60 秒的超时,然后重复等待。这也适用于重叠的 IO 和 IOCompletion 端口,如果您正在使用它们。

如果这是一个您要发送给其他人使用的应用程序,那么祝您好运。使用套接字时,Windows 可能是一个纯粹的混蛋......

于 2010-12-17T04:29:50.067 回答
1

我尝试将套接字选项设置为 REUSEADDR 但据我所知,这只影响重新连接到处于 TIME_WAIT 状态的端口。

这不太正确。它将允许您出于任何目的重新使用处于 TIME_WAIT 状态的端口,即侦听或连接。但我同意这无济于事。我对有关操作系统需要 10 分钟才能检测到崩溃的侦听器的评论感到惊讶。它应该在进程结束后立即清理所有资源,而不是处于 TIME_WAIT 状态的端口。

于 2010-12-17T01:44:58.493 回答
0

首先要检查的是,它确实是您的应用程序在该端口上侦听。采用:

netstat -anb

找出哪个进程正在侦听该端口。

要检查的第二件事是,当您的应用程序关闭时,您正在优雅地关闭套接字。如果您使用的高级套接字 API 应该不是什么大问题(您使用的是套接字 API,对吗?)。

最后,您的应用程序是如何构建的?有螺纹吗?它会启动其他进程吗?你怎么知道你的应用程序真的被关闭了?

于 2010-12-16T20:51:26.367 回答
0

netstat -ano

这将为您提供端口打开的进程的 PID。从任务管理器检查该过程。确保选中“列出所有用户的进程”。

于 2010-12-17T00:34:12.333 回答
0

http://hea-www.harvard.edu/~fine/Tech/addrinuse.html是“绑定:地址已在使用”错误的绝佳资源。

部分摘录:

TIME_WAIT 是通常在进程完成后占用端口几分钟的状态。相关超时的长度在不同的操作系统上有所不同,并且在某些操作系统上可能是动态的,但是典型值在 1 到 4 分钟的范围内。

避免策略

SO_REUSEADDR

这是减少“地址已在使用”错误的最简单和最有效的选择。

客户先关闭

如果远端发起关闭,则可以避免 TIME_WAIT。所以服务器可以通过让客户端先关闭来避免问题。

减少超时

如果(无论出于何种原因)这些选项都不适合您,也可以缩短与 TIME_WAIT 相关的超时。

于 2015-01-13T02:17:33.113 回答
0

在看到https://superuser.com/a/453827/56937后,我发现有一个WerFault进程被挂起。

它一定是从不存在的进程中继承了套接字,因为杀死它释放了我的监听端口。

于 2015-04-17T04:09:26.200 回答