进程已经退出,可是套接字仍然处于Listen状态

aiirr 2007-12-17 02:35:48
我使用ACE库做了一个AIO方面的程序,有的时候,当进程已经退出,用netstat看网络状态,发现端口仍然处于Listen状态。
例如:
netstat -anop TCP
获得一个列表,显示PID是1000(假设)的进程正在Listen某个端口(比如2000号端口)
而实际上,进程早已退出,用任务管理器看也看不到1000号进程。
奇怪的是用telnet xxx.xxx.xxx.xxx 2000
却可以连接到这个看不到的进程里。
结果导致我无法再次启动这个进程,因为端口已经处于Listen状态,我无法再次去绑定它
我已经设置了SO_REUSEADDR来防止套接字TIME_WAIT状态下的进程无法再次启动问题,可是套接字居然处于Listen状态,实在是奇怪。
注:
当进程退出的时候已经关闭了套接字,并且是正常关闭,关闭过程也没有出现问题
...全文
730 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
jimytang 2012-08-21
  • 打赏
  • 举报
回复 2
我在UNIX上也遇到过这样的问题,当时编写的一个起停程序的服务程序,也是百思不得其解,后来查了很久,才发现是由于程序调用system启动了其他程序,这样这个打开的句柄就复制到那个进程空间了,解决方法是使用端口前使用验证用户使用fcntl函数的参数F_SETFD 设置close-on-exec 旗标,解决了这个问题,至于window下的情况我就不清楚了,是不是你的程序也是启动了别的子进程,继承了这个socket。
aiirr 2007-12-26
  • 打赏
  • 举报
回复
注明一下,我关闭的socket是我自己创建的,不是其他进程创建的,这都不行,怀疑我和SetTcpEntry的友好度◎#¥%◎#
aiirr 2007-12-26
  • 打赏
  • 举报
回复
我关闭一个监听的socket,然后用GetTcpTable遍历所有的监听socket,如果发现我关闭的那个socket仍然在监听,我就用SetTcpEntry关调它。
但我调SetTcpEntry永远返回87号错误。
编写一个单独的应用程序去关闭端口,得到的结果是一样的
tcxjia 2007-12-26
  • 打赏
  • 举报
回复
DWORD SetTcpEntry(
PMIB_TCPROW pTcpRow // pointer to struct. with new state info
);
该函数是删除可疑TCP连接的,不知道你想怎么用他,难道客户端建立一个连接你删掉一个?
aiirr 2007-12-26
  • 打赏
  • 举报
回复
我曾经希望通过SetTcpEntry这个函数来关闭监听的端口,但这个函数总是返回错误码87,即参数不正确,我传递任何参数(我认为合法的和不合法的)给这个函数,它都返回这个错误码,太郁闷了,有人能够告诉我怎么做吗?
aiirr 2007-12-26
  • 打赏
  • 举报
回复
问题是如果这个监听的端口在一段时间内处于Listen状态,那么客户端(其实是另一个服务)会自动重新连接到这个没有进程关联的监听端口上,并傻傻的等待该端口上返回数据,如果只是傻傻的等待也就算了,关键是如果有连接连到这个没有进程关联的监听端口上,这个端口将不进入关闭状态。
一般来讲,用于通讯的数据socket将在closesocket后稍后才关闭(估计为了保障半连接特性),但用于监听的端口也在closesocket后不关闭,那我的麻烦就大了
aiirr 2007-12-25
  • 打赏
  • 举报
回复
我在代码中加入了GetTcpTable的相关代码,当closesocket后我遍历所有的套接字,如果我关闭的套接字还在监听,我就用_asm int 3让代码进入调试器,在调试器中我观察了调用的堆栈,发现closesocket确实被调用了,而且返回值是正确的,netstat 中显示端口也继续监听中,但过了很久,具体多久我没有注意,当我再次用netstat去看端口状态时,端口被释放了。问题时太久了,起码在10分钟以上,端口才释放
closesocket这个函数会被其他代码干扰吗?我确实调用了,得到的结果却不稳定,奇怪
my_girlf 2007-12-25
  • 打赏
  • 举报
回复
这是正常的,LZ不必担心.
王者荣耀zhou 2007-12-25
  • 打赏
  • 举报
回复
是的,他要等待一段时间才会关闭的,不是马上关闭,你可以看看TCP/IP 协议中的相关内容;
我用.net 开发的数据库程序也是这样的,通过网络连接到SQL Server,我已经关闭连接后SQL Server还是会等待一段时间才关闭,不然你可以测试,看是不是过一段时间后他会自动关闭~~
jourbin 2007-12-19
  • 打赏
  • 举报
回复
你在程序中加了伟哥吗?这么屹立坚挺!
开发人员中的一句话就是,电脑是不会骗人的,还是你自己代码里找吧
aiirr 2007-12-19
  • 打赏
  • 举报
回复
我增加了调试代码,分别在关闭数据通讯套接字和关闭监听套接字后面加上了closesocket函数的错误判断,如果有错就打印错误码,没有错就打印成功信息,结果成功信息打印出来(打印在文件里),程序也正常退出,可是用netstat一看,端口还在监听中,怎么会有这种事情?这种错误还不是每次都有,偶尔出现
aiirr 2007-12-17
  • 打赏
  • 举报
回复
主线程中有等待工作线程完成后才结束工作的代码,所以如果主线程已经结束,那么其他的工作线程也一定关闭了
stivenjia 2007-12-17
  • 打赏
  • 举报
回复
可能是那个Listen线程没有关闭把?
aiirr 2007-12-17
  • 打赏
  • 举报
回复
哦,我看到在ACE的库中有关闭listen套接字的代码,在析构函数中,因此库的使用者不用再次关闭listen的套接字
aiirr 2007-12-17
  • 打赏
  • 举报
回复
我怎么没有在任何官方的例子代码中看到关闭Listen的socket的代码?大侠,能否给个例子?
我看到的例子都是只关闭accept之后的socket,即用于I/O读写的那个socket,那个用于被动等待连接的socket似乎没有看过关闭它的例子
aa3000 2007-12-17
  • 打赏
  • 举报
回复
所有的 socket 都要关闭
awperpvip 2007-12-17
  • 打赏
  • 举报
回复
晕...Listen的那个socket当然要关闭啦
aiirr 2007-12-17
  • 打赏
  • 举报
回复
listen的套接字我没有去关闭它,关闭的是accept后的套接字,难道需要关闭listen的套接字?从没有看到有文献说要关闭它啊!
aiirr 2007-12-17
  • 打赏
  • 举报
回复
由于是使用ACE的前摄器框架写的代码,无法贴出完整的代码,不过关闭的代码很简单:
ACE_OS::shutdown (handle (), SD_BOTH);
ACE_OS::closesocket (handle ());

相当于
socket sock;
...
...
shutdown (sock);
closesocket (sock);

其实我感到无法解决的是我的进程已经退出了,我即便检查到closesocket的错误,我也拿它没有办法。
awperpvip 2007-12-17
  • 打赏
  • 举报
回复
当进程退出的时候已经关闭了套接字,并且是正常关闭,关闭过程也没有出现问题
贴点代码啊,注释太少了,不好判断,我猜的:
Listen的那个socket,正常关闭是不是成功关闭呢?WSAGetLastError()
加载更多回复(3)

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧