应用程序崩溃后套接字仍在侦听
我在 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 Sockets API。
编辑:
显然这个问题没有解决方案,因此对于开发,我将使用代理/工具来解决它。感谢所有的建议,非常感谢。
I'm having a problem with one of my C++ applications on Windows 2008x64 (same app runs just fine on Windows 2003x64).
After a crash or even sometimes after a regular shutdown/restart cycle it has a problem using a socket on port 82 it needs to receive commands.
Looking at netstat I see the socket is still in listening state more than 10 minutes after the application stopped (the process is definitely not running anymore).
TCP 0.0.0.0:82 LISTENING
I tried setting the socket option to REUSEADDR but as far as I know that only affects re-connecting to a port that's in TIME_WAIT state. Either way this change didn't seem to make any difference.
int doReuse = 1;
setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR,
(const char *)&doReuse, sizeof(doReuse));
Any ideas what I can do to solve or at least avoid this problem?
EDIT:
Did netstat -an but this is all I am getting:
TCP 0.0.0.0:82 0.0.0.0:0 LISTENING
For netstat -anb I get:
TCP 0.0.0.0:82 0.0.0.0:0 LISTENING
[System]
I'm aware of shutting down gracefully, but even if the app crashes for some reason I still need to be able to restart it. The application in question uses an in-house library that internally uses Windows Sockets API.
EDIT:
Apparently there is no solution for this problem, so for development I will go with a proxy / tool to work around it. Thanks for all the suggestions, much appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
如果这只是在调试时对您造成伤害,请使用 sysinternals 人员的 tcpview强制关闭套接字。我假设它适用于您的平台,但我不确定。
如果您在任何套接字上执行阻塞操作,请勿使用无限期超时。根据我的经验,这可能会在多处理器计算机上导致奇怪的行为。我不确定它是什么 Windows 服务器操作系统,但是,它是 2003 Server 之前的一两个版本。
不要使用无限期的超时,而是使用 30 到 60 秒的超时,然后重复等待。如果您正在使用重叠的 IO 和 IOCompletion 端口,这也适用于它们。
如果这是您要发布给其他人使用的应用程序,祝您好运。当使用套接字时,Windows 可能是一个纯粹的混蛋......
If this is only hurting you at debug time, use tcpview from the sysinternals folks to force the socket closed. I am assuming it works on your platform, but I am not sure.
If you're doing blocking operations on any sockets, do not use an indefinite timeout. This can cause weird behavior on a multiprocessor machine in my experience. I'm not sure what Windows server OS it was, but, it was one or two versions previous to 2003 Server.
Instead of an indefinite timeout, use a 30 to 60 second timeout and then just repeat the wait. This goes for overlapped IO and IOCompletion ports as well, if you're using them.
If this is an app you're shipping for others to use, good luck. Windows can be a pure bastard when using sockets...
这不太正确。它允许您出于任何目的重新使用处于 TIME_WAIT 状态的端口,即监听或连接。但我同意这对这件事没有帮助。关于操作系统需要 10 分钟才能检测到崩溃的侦听器的评论让我感到惊讶。它应该在进程结束后立即清理除处于 TIME_WAIT 状态的端口之外的所有资源。
That's not quite correct. It will let you re-use a port in TIME_WAIT state for any purpose, i.e. listen or connect. But I agree it won't help with this. I'm surprised by the comment about the OS taking 10 minutes to detect the crashed listener. It should clean up all resources as soon as the process ends, other than ports in the TIME_WAIT state.
首先要检查的是您的应用程序确实正在侦听该端口。使用:
netstat -anb
找出哪个进程正在侦听该端口。
要检查的第二件事是,当应用程序关闭时,您是否正常关闭套接字。如果您使用的是高级套接字 API,那么这应该不是什么太大的问题(您正在使用套接字 API,对吧?)。
最后,您的应用程序是如何构建的?是有螺纹的吗?它会启动其他进程吗?你怎么知道你的应用程序真的被关闭了?
The first thing to check is that it really is your application listening on that port. Use:
netstat -anb
to figure out which process is listenin on that port.
The second thing to check is that your are closing the socket gracefully when your application shuts down. If you're using a high-level socket API that shouldn't be too much of an issue (you are using a socket API, right?).
Finally, how is your application structured? Is it threaded? Does it launch other processes? How do you know that your application is really shut down?
运行
netstat -ano
这将为您提供打开端口的进程的 PID。从任务管理器检查该进程。确保选中“列出所有用户的进程”。
Run
netstat -ano
This will give you the PID of the process that has the port open. Check that process from the task manager. Make sure you have "list processes from all users" is checked.
http://hea-www.harvard.edu/~fine/Tech/ addrinuse.html 是解决“Bind: Address Already in Use”错误的重要资源。
一些摘录:
http://hea-www.harvard.edu/~fine/Tech/addrinuse.html is a great resource for "Bind: Address Already in Use" errors.
Some extracts:
看到https://superuser.com/a/453827/56937后我发现有一个
WerFault< /code> 已挂起的进程。
它一定是从不存在的进程继承了套接字,因为杀死它会释放我的监听端口。
After seeing https://superuser.com/a/453827/56937 I discovered that there was a
WerFault
process that was suspended.It must have inherited the sockets from the non-existent process because killing it freed up my listening ports.