进程已经退出,可是套接字仍然处于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状态,实在是奇怪。
注:
当进程退出的时候已经关闭了套接字,并且是正常关闭,关闭过程也没有出现问题
...全文
1096 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)
本PDF电子书包含上下两册,共1576页,带目录,高清非扫描版本。 作者: 毛德操 胡希明 丛书名: Linux内核源代码情景分析 出版社:浙江大学出版社 目录 第1章 预备知识 1.1 Linux内核简介. 1.2 Intel X86 CPU系列的寻址方式 1.3 i386的页式内存管理机制 1.4 Linux内核源代码中的C语言代码 1.5 Linux内核源代码中的汇编语言代码 第2章 存储管理 2.1 Linux内存管理的基本框架 2.2 地址映射的全过程 2.3 几个重要的数据结构和函数 2.4 越界访问 2.5 用户堆栈的扩展 2.6 物理页面的使用和周转 2.7 物理页面的分配 2.8 页面的定期换出 2.9 页面的换入 2.10 内核缓冲区的管理 2.11 外部设备存储空间的地址映射 2.12 系统调用brk() 2.13 系统调用mmap() 第3章 中断、异常和系统调用 3.1 X86 CPU对中断的硬件支持 3.2 中断向量表IDT的初始化 3.3 中断请求队列的初始化 3.4 中断的响应和服务 3.5 软中断与Bottom Half 3.6 页面异常的进入和返回 3.7 时钟中断 3.8 系统调用 3.9 系统调用号与跳转表 第4章 进程进程调度 4.1 进程四要素 4.2 进程三部曲:创建、执行与消亡 4.3 系统调用fork()、vfork()与clone() 4.4 系统调用execve() 4.5 系统调用exit()与wait4() 4.6 进程的调度与切换 4.7 强制性调度 4.8 系统调用nanosleep()和pause() 4.9 内核中的互斥操作 第5章 文件系统 5.1 概述 5.2 从路径名到目标节点 5.3 访问权限与文件安全性 5.4 文件系统的安装和拆卸 5.5 文件的打开与关闭 5.6 文件的写与读 5.7 其他文件操作 5.8 特殊文件系统/proc 第6章 传统的Unix进程间通信 6.1 概述 6.2 管道和系统调用pipe() 6.3 命名管道 6.4 信号 6.5 系统调用ptrace()和进程跟踪 6.6 报文传递 6.7 共享内存 6.8 信号量 第7章基于socket的进程间通信 7.1系统调用socket() 7.2函数sys—socket()——创建插口 7.3函数sys—bind()——指定插口地址 7.4函数sys—listen()——设定server插口 7.5函数sys—accept()——接受连接请求 7.6函数sys—connect()——请求连接 7.7报文的接收与发送 7.8插口的关闭 7.9其他 第8章设备驱动 8.1概述 8.2系统调用mknod() 8.3可安装模块 8.4PCI总线 8.5块设备的驱动 8.6字符设备驱动概述 8.7终端设备与汉字信息处理 8.8控制台的驱动 8.9通用串行外部总线USB 8.10系统调用select()以及异步输入/输出 8.11设备文件系统devfs 第9章多处理器SMP系统结构 9.1概述 9.2SMP结构中的互斥问题 9.3高速缓存与内存的一致性 9.4SMP结构中的中断机制 9.5SMP结构中的进程调度 9.6SMP系统的引导 第10章系统引导和初始化 10.1系统引导过程概述 10.2系统初始化(第一阶段) 10.3系统初始化(第二阶段) 10.4系统初始化(第三阶段) 10.5系统的关闭和重引导

18,358

社区成员

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

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