我使用ACE库做了一个AIO方面的程序,有的时候,当进程已经退出,用netstat看网络状态,发现端口仍然处于Listen状态。
例如:
netstat -anop TCP
获得一个列表,显示PID是1000(假设)的进程正在Listen某个端口(比如2000号端口)
而实际上,进程早已退出,用任务管理器看也看不到1000号进程。
奇怪的是用telnet xxx.xxx.xxx.xxx 2000
却可以连接到这个看不到的进程里。
结果导致我无法再次启动这个进程,因为端口已经处于Listen状态,我无法再次去绑定它
我已经设置了SO_REUSEADDR来防止套接字TIME_WAIT状态下的进程无法再次启动问题,可是套接字居然处于Listen状态,实在是奇怪。
注:
当进程退出的时候已经关闭了套接字,并且是正常关闭,关闭过程也没有出现问题

解决方案 »

  1.   

    再附加一些说明:选择的是windows的完成端口机制来实现异步通讯的
      

  2.   

    closesocket,或者 shutdown??
    或者可能是要等一下系统才关闭你的socket.
      

  3.   

    不太可能,我输出了调试信息,进程中的相关线程依次调用了shutdown和closesocket。可套接字顽强的处于
    Listen状态并持续很久,当然这样的情况偶然才会发生,而且从不在调试器中发生,郁闷死了
      

  4.   

    当进程退出的时候已经关闭了套接字,并且是正常关闭,关闭过程也没有出现问题
    贴点代码啊,注释太少了,不好判断,我猜的:
    Listen的那个socket,正常关闭是不是成功关闭呢?WSAGetLastError()
      

  5.   

    由于是使用ACE的前摄器框架写的代码,无法贴出完整的代码,不过关闭的代码很简单:
    ACE_OS::shutdown (handle (), SD_BOTH);
    ACE_OS::closesocket (handle ());相当于
    socket sock;
    ...
    ...
    shutdown (sock);
    closesocket (sock);其实我感到无法解决的是我的进程已经退出了,我即便检查到closesocket的错误,我也拿它没有办法。
      

  6.   

    listen的套接字我没有去关闭它,关闭的是accept后的套接字,难道需要关闭listen的套接字?从没有看到有文献说要关闭它啊!
      

  7.   

    晕...Listen的那个socket当然要关闭啦
      

  8.   

    所有的 socket 都要关闭
      

  9.   

    我怎么没有在任何官方的例子代码中看到关闭Listen的socket的代码?大侠,能否给个例子?
    我看到的例子都是只关闭accept之后的socket,即用于I/O读写的那个socket,那个用于被动等待连接的socket似乎没有看过关闭它的例子
      

  10.   

    哦,我看到在ACE的库中有关闭listen套接字的代码,在析构函数中,因此库的使用者不用再次关闭listen的套接字
      

  11.   

    可能是那个Listen线程没有关闭把?
      

  12.   

    我增加了调试代码,分别在关闭数据通讯套接字和关闭监听套接字后面加上了closesocket函数的错误判断,如果有错就打印错误码,没有错就打印成功信息,结果成功信息打印出来(打印在文件里),程序也正常退出,可是用netstat一看,端口还在监听中,怎么会有这种事情?这种错误还不是每次都有,偶尔出现
      

  13.   

    我在代码中加入了GetTcpTable的相关代码,当closesocket后我遍历所有的套接字,如果我关闭的套接字还在监听,我就用_asm int 3让代码进入调试器,在调试器中我观察了调用的堆栈,发现closesocket确实被调用了,而且返回值是正确的,netstat 中显示端口也继续监听中,但过了很久,具体多久我没有注意,当我再次用netstat去看端口状态时,端口被释放了。问题时太久了,起码在10分钟以上,端口才释放
    closesocket这个函数会被其他代码干扰吗?我确实调用了,得到的结果却不稳定,奇怪
      

  14.   

    是的,他要等待一段时间才会关闭的,不是马上关闭,你可以看看TCP/IP 协议中的相关内容;
    我用.net 开发的数据库程序也是这样的,通过网络连接到SQL Server,我已经关闭连接后SQL Server还是会等待一段时间才关闭,不然你可以测试,看是不是过一段时间后他会自动关闭~~
      

  15.   

    问题是如果这个监听的端口在一段时间内处于Listen状态,那么客户端(其实是另一个服务)会自动重新连接到这个没有进程关联的监听端口上,并傻傻的等待该端口上返回数据,如果只是傻傻的等待也就算了,关键是如果有连接连到这个没有进程关联的监听端口上,这个端口将不进入关闭状态。
    一般来讲,用于通讯的数据socket将在closesocket后稍后才关闭(估计为了保障半连接特性),但用于监听的端口也在closesocket后不关闭,那我的麻烦就大了
      

  16.   

    我曾经希望通过SetTcpEntry这个函数来关闭监听的端口,但这个函数总是返回错误码87,即参数不正确,我传递任何参数(我认为合法的和不合法的)给这个函数,它都返回这个错误码,太郁闷了,有人能够告诉我怎么做吗?
      

  17.   

    DWORD SetTcpEntry( 
    PMIB_TCPROW pTcpRow // pointer to struct. with new state info  
    ); 
    该函数是删除可疑TCP连接的,不知道你想怎么用他,难道客户端建立一个连接你删掉一个?
      

  18.   

    我关闭一个监听的socket,然后用GetTcpTable遍历所有的监听socket,如果发现我关闭的那个socket仍然在监听,我就用SetTcpEntry关调它。
    但我调SetTcpEntry永远返回87号错误。
    编写一个单独的应用程序去关闭端口,得到的结果是一样的
      

  19.   

    注明一下,我关闭的socket是我自己创建的,不是其他进程创建的,这都不行,怀疑我和SetTcpEntry的友好度◎#¥%◎#
      

  20.   

    我在UNIX上也遇到过这样的问题,当时编写的一个起停程序的服务程序,也是百思不得其解,后来查了很久,才发现是由于程序调用system启动了其他程序,这样这个打开的句柄就复制到那个进程空间了,解决方法是使用端口前使用验证用户使用fcntl函数的参数F_SETFD 设置close-on-exec 旗标,解决了这个问题,至于window下的情况我就不清楚了,是不是你的程序也是启动了别的子进程,继承了这个socket。