服务器程序为Socket Sever,绑定12005端口,启动就Listen,然后客户端不停的连接、断开,在每天4点服务器程序自动关闭后,又由另外一个守候程序打开。服务器运行8-9天后,客户端不能连接了,连接的客户端也请求不了数据,就是说服务器程序不接受SOCKET连接了,发送的数据在OnReceive()不能接受了,在这个时间用远程登录可以登录到服务器,CPU也是4%左右,自己的服务器程序用内存也是不到10M(曾经到过70M也没问题),数据的一条线城也没有堵塞(当时自己打开SQL2000企业管理器查看到的),关闭自己服务器程序,客户端又可以连接上来,但是过了2个小时又是上面的情况,这次关闭自己服务器程序也不能连接了,只好将操作系统关闭,重新启动服务器机器,重起后可以了。又要运行到8-9天后才发生重复的事情、、、,好奇怪呀,已经连续发生4次了,找不到原因,自己认为
1、是不是操作系统的端口8-9天后用完了?如果是
2、内存用完了?(1G系统内存,在资源管理器看到是一直稳定到830M左右)

解决方案 »

  1.   

    在OnClose()
    中直接用了Close();
      

  2.   

    因为服务器是两块SCISI硬盘组成的RAID1,会不会是RAID卡或硬盘不同步的问题呢?
      

  3.   

    TCP连接如果不收发数据,大约几十秒之后就会超时,超时之后服务器端不会收到OnClose()
    这样一来,就会有许多死连接,服务器端无法清除。
    Windows 2000 pro(SP4)上大约能创建2200个Socket(实测数据!),一旦达到这个数量就无法创建新的Socket,当然不会接受连接了
    C/S之间没有数据发送的时候要发送一些在线包,比如说,没有数据传输时每20秒发送一个空格
    Server端对每个连接定时检测,大概象下面这样:
    OnRecv()
    {
      last_recv_time = GetTickCount();
      //do recv() here
    }OnTimer()
    {
      if(GetTickCount()-last_recv_time>35000)//close connection any way after 35 seconds' idle
      {
        closesocket(s)
      }
    }
      

  4.   

    TCP连接如果不收发数据,大约几十秒之后就会超时,超时之后服务器端不会收到OnClose()
    这样一来,就会有许多死连接,服务器端无法清除。
    Windows 2000 pro(SP4)上大约能创建2200个Socket(实测数据!),一旦达到这个数量就无法创建新的Socket,当然不会接受连接了
    对于在线和下线的时间我有专门记录来查询的,一天一般不会超过20个用户异常断线(比如网线掉线等),所以说不可能达到您所说的2200个SOCKET的问题,而且我在每天4点时服务程序会自动关闭然后由守侯程序打开,目的也是为了释放一些死连接和重新连接数据库,是不是这样也无法释放那些死连接?一直到8天后死连接达到了极限,就才有那样的问题了?但是也是不到200个死连接呀?
      

  5.   

    我这里的情况是: 
    一天一般都有300-400个连接,同时在线不超过100个。8天就是达到了2500个连接左右,是不是服务器的Close() SOCKET不成功,我是在OnClose()中直接Close()的。 hjunxu(hjun) ( )
    有没有看一下出问题的时候端口情况是怎么样的阿?请问如何查端口的情况呀?
      

  6.   

    楼主,这个问题很好解决呀,小Case啦每次要读写数据库就连接一次,读写完就断开连接就行了。保证不再出现死连接。
      

  7.   

    另外socket连接加心跳包检测呀。你的程序不是直接连数据库吗?难道是连socket 发sql语句给socket,由socket转发给数据库???
    数据库数据在转发给socket??为什么客户端不直接连数据库捏?难道又是因为lisence
      

  8.   

    test2002(test2002)另外socket连接加心跳包检测呀,每次要读写数据库就连接一次,读写完就断开连接就行了。
    请问如何socket连接加心跳包检测呀?不是数据库的问题,也不是licence的问题。每次要读写数据库就连接一次,读写完就断开连接,这样会产生效率的问题的,应该对数据库长 连接才好吧。
      

  9.   

    看看你进程里的Socket数是多少?
      

  10.   

    1。对数据库长连接用数据库缓冲池,例子网上有好多,你自己搜搜2。每个连接上来的客户端给服务器发”心跳包“,自己定义一下这个包的格式,每隔一段时间(自己定,一般1-3分钟)就发检测包,服务器接收,如果超过这个时间没有收到就关闭该连接
    这个可以参照楼上: DoItFreely(Freely) ( ) 信誉:95 的方法做
    客户端要有重连机制
      

  11.   


    有没有看一下出问题的时候端口情况是怎么样的阿?
    ---------------
    netstat -na就好了.
      

  12.   

    服务器端不管有多少用户来连,只会开一个侦听端口的。肯定不是端口问题, 有可能是SOCKET句柄未正常关闭引起的。如果实在不行,就等问题出现的时候,你再连接的时候,抓一下TCP的3次握手包, 看是哪一次握手出了问题。
      

  13.   

    资源泄露吧,
    检查服务器里的资源分配和释放代码,
    因为你每天CLOSE,所以不可能是SOCKET导致的问题,
    进程退出,进程的SOCKET HANDLE资源就被完全释放,
      

  14.   

    BOOL CMySocket::IsConnectionDropDown()
    {
    BOOL bConnDropped = FALSE;
    INT iRet = 0;
    BOOL bOK = TRUE;

    if (m_hSocket == INVALID_SOCKET)
    return TRUE; struct timeval timeout = { 0, 0 };
    fd_set readSocketSet;

    FD_ZERO(&readSocketSet);
    FD_SET(m_hSocket, &readSocketSet);

    iRet = ::select(0, &readSocketSet, NULL, NULL, &timeout);
    bOK = (iRet > 0);

    if(bOK)
    {
    bOK = FD_ISSET(m_hSocket, &readSocketSet);
    }

    if(bOK)
    {
    CHAR szBuffer[1] = "";
    iRet = ::recv(m_hSocket, szBuffer, 1, MSG_PEEK);
    bOK = (iRet > 0);
    if(!bOK)
    {
    INT iError = ::WSAGetLastError();
    bConnDropped = (( iError == WSAENETRESET) ||
    (iError == WSAECONNABORTED) ||
    (iError == WSAECONNRESET) ||
    (iError == WSAEINVAL) ||
    (iRet == 0));
    }
    }
        return(bConnDropped);}心跳包检测函数。
      

  15.   

    用CommView监视有多少个活动连接,CommView默认只显示最近20个IP,你设大一点。
    一段时间之后,比如5分钟,如果活动的地址数(IP:Port)远小于“在线数”,说明有很多死连接
      

  16.   

    danscort2000(带鱼丝考) 同意应当是资源没有释放
    你说的问题我不太清楚,不过我前两天遇到一个问题我做的是远程控制系统,上位机操作系统是WINDOWS 2000下位机是WINDOWS 98我用上位机发具体的命令控制下位机的程序运行,结果我的下位机程序会在几个小时内死机,后来同事说有可能是资源的事情,我查了一下没有资源泄露啊(通过VC调试器)可是后来他帮我仔细的检查了一下代码,才发现真是问题多多,希望这些对你有帮助.
    呵呵我的下位机硬盘512M处理器是奔三的内存32M!!!我想和你的服务器相比时间是很成比例的.
    同情!!!!!!
      

  17.   

    建议:等出现问题,手动关闭socket,再连看看
      

  18.   

    回复人: test2002(test2002) ( ) 信誉:81  2005-11-22 16:49:00  得分: 0  
     
     
       怎样保证长连接捏。
    我这么设想吧,设置数据库连接和执行时间,如果连接超时则连接失败,
    如果执行超时,则认为这次连接已断开,继续重新连接,
    这些是监测是否断,要防止断,我想还得往数据库发语句来检测吧。
      
     
    我也不是很清楚什么是长连接,但是我的客户端连上后如果一个小时不操作,然后再请求或发送数据也是很正常的,说明SOCKET是没断的,而且数据库也是连接上的,这不知道算不算是长连接,数据库读取用的是OLEDB技术。 
    flashboy(爱写程序的小绵羊) 服务器端不管有多少用户来连,只会开一个侦听端口的。肯定不是端口问题, 有可能是SOCKET句柄未正常关闭引起的。如果实在不行,就等问题出现的时候,你再连接的时候,抓一下TCP的3次握手包, 看是哪一次握手出了问题。
    有可能是SOCKET句柄未正常关闭引起的 、、、
    我在CSocket的OnClose()函数中直接Close(),这是不是正常关闭了。
    抓一下TCP的3次握手包, 看是哪一次握手出了问题
    请问如何抓呀?
      

  19.   

    谢谢大家的支持。DoItFreely(Freely) ( 用CommView监视有多少个活动连接,CommView默认只显示最近20个IP,你设大一点。
    一段时间之后,比如5分钟,如果活动的地址数(IP:Port)远小于“在线数”,说明有很多死连接CommView在那里找到?还是DOS命令?
    我的操作系统是Win2003 SP1加MSSQL2000 SP4。
      

  20.   

    danscort2000(带鱼丝考) ( ) 信誉:97  2005-11-22 16:33:00  得分: 0  
     
    建议你不要定时关闭,就是不要守护进程,
    让它连续运行,看到第几天出问题
      
     
    我以前试过,一天就有问题了,后来重写了服务器的代码,加上守侯程序处理,就变成了8-9天的时间了。
      

  21.   

    blackpearl2(黑珍珠):我也不是很清楚什么是长连接,但是我的客户端连上后如果一个小时不操作,然后再请求或发送数据也是很正常的,说明SOCKET是没断的,而且数据库也是连接上的,这不知道算不算是长连接,数据库读取用的是OLEDB技术。一两个小时算很长吗?
    OLEDB技术如果是几十个小时长时间连接肯定也会断的不过,其实断了也没什么,做个超时检测,如果超时,则认为断了重关闭,再连。
      

  22.   

    socket连接肯定要心跳包的,抓包其实也没什么意思。楼主如果socket发数据前检测socket断否,则不会存在什么问题了,有些服务器会主动关socket,如果再他规定时间没包来的话。
      

  23.   

    我用机器连续测试了三天,SOCKET连接达到了50000次,服务器都是正常的,只是连接多的时候速度慢而已,全部关闭后,又很快了。到底是什么原因呢?请大家再多提建议,希望能够解决。测试的环境除了硬盘不同外(测试的为普通PC,普通硬盘。真实环境是HP服务器,SICSI硬盘组成的RAID1),全部一样的。
      

  24.   

    ,发送的数据在OnReceive()不能接受了,在这个时间用远程登录可以登录到服务器,CPU也是4%左右
    -----------------------------
    问题很明显,肯定是端口用完了,telnet证明你的监听是有效的,但不是能accept了,就是分配不到端口了,关闭时你多半没有调用closesocket(),closesocket之前最好还调用一个shutdown(s, SD_BOTH)来温柔关闭。
      

  25.   

    服务器有没有设置SO_REUSEADDR 重用端口
    netstat -a 看看,是否有许多 TIME_WAIT状态的连接没有释放占用了端口
      

  26.   

    客户端不停的连接和断开了100次这是服务器的:Active Connections  Proto  Local Address          Foreign Address        State
      TCP    kcrjserver:http        kcrjserver:0           LISTENING
      TCP    kcrjserver:epmap       kcrjserver:0           LISTENING
      TCP    kcrjserver:microsoft-ds  kcrjserver:0           LISTENING
      TCP    kcrjserver:1025        kcrjserver:0           LISTENING
      TCP    kcrjserver:1033        kcrjserver:0           LISTENING
      TCP    kcrjserver:ms-sql-s    kcrjserver:0           LISTENING
      TCP    kcrjserver:3389        kcrjserver:0           LISTENING
      TCP    kcrjserver:11111       kcrjserver:0           LISTENING
      TCP    kcrjserver:12005       kcrjserver:0           LISTENING
      TCP    kcrjserver:1034        kcrjserver:ms-sql-s    ESTABLISHED
      TCP    kcrjserver:ms-sql-s    kcrjserver:1034        ESTABLISHED
      TCP    kcrjserver:ms-sql-s    kcrjserver:1689        ESTABLISHED
      TCP    kcrjserver:1689        kcrjserver:ms-sql-s    ESTABLISHED
      TCP    kcrjserver:netbios-ssn  kcrjserver:0           LISTENING
      TCP    kcrjserver:3389        KCRJ:1224              ESTABLISHED
      TCP    kcrjserver:12005       KCRJ:1271              ESTABLISHED
      UDP    kcrjserver:microsoft-ds  *:*
      UDP    kcrjserver:isakmp      *:*
      UDP    kcrjserver:1036        *:*
      UDP    kcrjserver:1148        *:*
      UDP    kcrjserver:ms-sql-m    *:*
      UDP    kcrjserver:4500        *:*
      UDP    kcrjserver:38037       *:*
      UDP    kcrjserver:ntp         *:*
      UDP    kcrjserver:bootps      *:*
      UDP    kcrjserver:bootpc      *:*
      UDP    kcrjserver:ntp         *:*
      UDP    kcrjserver:netbios-ns  *:*
      UDP    kcrjserver:netbios-dgm  *:*
      UDP    kcrjserver:2051        *:*
      UDP    kcrjserver:2535        *:*
     
    这是客户端的:Microsoft Windows [版本 5.2.3790]
    (C) 版权所有 1985-2003 Microsoft Corp.C:\Documents and Settings\Administrator>netstat -aActive Connections  Proto  Local Address          Foreign Address        State
      TCP    kcrj:http              kcrj:0                 LISTENING
      TCP    kcrj:epmap             kcrj:0                 LISTENING
      TCP    kcrj:microsoft-ds      kcrj:0                 LISTENING
      TCP    kcrj:1025              kcrj:0                 LISTENING
      TCP    kcrj:ms-sql-s          kcrj:0                 LISTENING
      TCP    kcrj:11111             kcrj:0                 LISTENING
      TCP    kcrj:1301              kcrj:ms-sql-s          ESTABLISHED
      TCP    kcrj:ms-sql-s          kcrj:1301              ESTABLISHED
      TCP    kcrj:netbios-ssn       kcrj:0                 LISTENING
      TCP    kcrj:1224              KCRJSERVER:3389        ESTABLISHED
      TCP    kcrj:1284              KCRJSERVER:12005       TIME_WAIT
      TCP    kcrj:1302              KCRJSERVER:12005       TIME_WAIT
      TCP    kcrj:1303              KCRJSERVER:12005       TIME_WAIT
      TCP    kcrj:1304              KCRJSERVER:12005       TIME_WAIT
      TCP    kcrj:1305              KCRJSERVER:12005       TIME_WAIT
      TCP    kcrj:1306              KCRJSERVER:12005       TIME_WAIT
      TCP    kcrj:1307              KCRJSERVER:12005       TIME_WAIT
      TCP    kcrj:1308              KCRJSERVER:12005       TIME_WAIT
      TCP    kcrj:1309              KCRJSERVER:12005       TIME_WAIT
      TCP    kcrj:1310              KCRJSERVER:12005       TIME_WAIT
      TCP    kcrj:1311              KCRJSERVER:12005       TIME_WAIT
      TCP    kcrj:1312              KCRJSERVER:12005       TIME_WAIT
      TCP    kcrj:1313              KCRJSERVER:12005       TIME_WAIT
      TCP    kcrj:1314              KCRJSERVER:12005       TIME_WAIT
      TCP    kcrj:1315              KCRJSERVER:12005       TIME_WAIT
      TCP    kcrj:1316              KCRJSERVER:12005       TIME_WAIT
      TCP    kcrj:1317              KCRJSERVER:12005       TIME_WAIT
      TCP    kcrj:1318              KCRJSERVER:12005       TIME_WAIT
      TCP    kcrj:1319              KCRJSERVER:12005       TIME_WAIT
      TCP    kcrj:1320              KCRJSERVER:12005       TIME_WAIT
      TCP    kcrj:1321              KCRJSERVER:12005       TIME_WAIT
      TCP    kcrj:1322              KCRJSERVER:12005       TIME_WAIT
      TCP    kcrj:1323              KCRJSERVER:12005       TIME_WAIT
      TCP    kcrj:1324              KCRJSERVER:12005       TIME_WAIT5分种后客户端的;
    Active Connections  Proto  Local Address          Foreign Address        State
      TCP    kcrj:http              kcrj:0                 LISTENING
      TCP    kcrj:epmap             kcrj:0                 LISTENING
      TCP    kcrj:microsoft-ds      kcrj:0                 LISTENING
      TCP    kcrj:1025              kcrj:0                 LISTENING
      TCP    kcrj:ms-sql-s          kcrj:0                 LISTENING
      TCP    kcrj:11111             kcrj:0                 LISTENING
      TCP    kcrj:1301              kcrj:ms-sql-s          ESTABLISHED
      TCP    kcrj:ms-sql-s          kcrj:1301              ESTABLISHED
      TCP    kcrj:netbios-ssn       kcrj:0                 LISTENING
      TCP    kcrj:1224              KCRJSERVER:3389        ESTABLISHED
      TCP    kcrj:netbios-ssn       kcrj:0                 LISTENING
      TCP    kcrj:netbios-ssn       kcrj:0                 LISTENING
      UDP    kcrj:microsoft-ds      *:*
      UDP    kcrj:isakmp            *:*
      UDP    kcrj:1030              *:*
      UDP    kcrj:1225              *:*
      UDP    kcrj:ms-sql-m          *:*
      UDP    kcrj:4500              *:*
      UDP    kcrj:38037             *:*
      UDP    kcrj:ntp               *:*
      UDP    kcrj:1230              *:*
      UDP    kcrj:ntp               *:*
      UDP    kcrj:netbios-ns        *:*
      UDP    kcrj:netbios-dgm       *:*
      UDP    kcrj:2051              *:*
      UDP    kcrj:ntp               *:*
      UDP    kcrj:netbios-ns        *:*
      UDP    kcrj:netbios-dgm       *:*
      UDP    kcrj:ntp               *:*
      UDP    kcrj:netbios-ns        *:*
      UDP    kcrj:netbios-dgm       *:*
      

  27.   

    看起来好象是客户端没有释放到,服务器却是释放到的,难道客户端会对服务器造成影响吗?
    好象有一点眉头了,谢谢大家的支持,希望能够解决这一难题。somexing(张星星
    服务器有没有设置SO_REUSEADDR 重用端口
    netstat -a 看看,是否有许多 TIME_WAIT状态的连接没有释放占用了端口谢谢您的提示,请问服务器如何设置SO_REUSEADDR 重用端口??? Delphityro(菜鸟也是人) ( ) 信誉:100  2005-11-23 23:28:00  得分: 0  
     
     
       ,发送的数据在OnReceive()不能接受了,在这个时间用远程登录可以登录到服务器,CPU也是4%左右
    -----------------------------
    问题很明显,肯定是端口用完了,telnet证明你的监听是有效的,但不是能accept了,就是分配不到端口了,关闭时你多半没有调用closesocket(),closesocket之前最好还调用一个shutdown(s, SD_BOTH)来温柔关闭。
      
     
    我在OnAccept()中有检测的,如果accept失败,就写入一个文本,是否端口用完连OnAccept()函数都进不去了,关闭服务器程序她会不会又自动将端口释放出来呢?
      

  28.   

    我用机器连续测试了三天,SOCKET连接达到了50000次,服务器都是正常的,端口好象又不是用完了的感觉呀。
      

  29.   

    可以加心跳,
    比方20秒钟发送一个包
    对方收到就返回一个包回来连续3次没收到返回包,就认定链路断了
    就可以closesocket();
    这样可以及时释放资源.
      

  30.   

    setsockopt 函数 设置  SO_REUSEADDR 还有 SO_LINGER
      

  31.   

    很可能是socket资源没有释放掉,造成虚拟内存持续增加,当虚拟内存增加到一定数量是,新的socket资源申请就会失败。
      

  32.   

    当客户端不能接收到你发送的数据时,应该关闭该SOCKET,并释放出来
    同时在客户端退出前告知服务器,并关闭该连接的SOCKET,并释放
      

  33.   

    freemme(路在脚下) ( ) 信誉:100  2005-11-25 11:39:00  得分: 0  
     
     
       很可能是socket资源没有释放掉,造成虚拟内存持续增加,当虚拟内存增加到一定数量是,新的socket资源申请就会失败。
      
     
    在不能连接时,在资源管理器中看到内存是800M左右(一直都稳定的,系统是1G的内存)。: liuwei200000(太阳神) ( ) 信誉:100  2005-11-25 11:42:00  得分: 0  
     
     
       当客户端不能接收到你发送的数据时,应该关闭该SOCKET,并释放出来
    同时在客户端退出前告知服务器,并关闭该连接的SOCKET,并释放
      
    服务器是这样写,如果Send(s,s.GetLength)==SOCKET_ERROR 就关闭该SOCKET,所以说服务器是已经将SOCKET关闭了的。客户端Connect每次都是成功的,就不知道为什么服务器不返回数据,正常的话马上就返回数据了。
      

  34.   

    anothermxw() ( ) 我说个理由吧,服务器程序那边既没有死掉,也不能接受连接,可能的原因是程序中锁住了,导致无法响应。我遇上过这种问题。但是客户端connect是成功的,如果程序锁住了,就连connect也不会成功吧?
      

  35.   

    anothermxw() ( ) 我说个理由吧,服务器程序那边既没有死掉,也不能接受连接,可能的原因是程序中锁住了,导致无法响应。我遇上过这种问题。但是客户端connect是成功的,如果程序锁住了,就连connect也不会成功吧?CPU也应该是100%的吧?(在这个时间用远程登录可以登录到服务器,CPU也是4%左右,)
      

  36.   

    Socekt Accept应该用的是物理内存中的核心内存
    LZ查看一下出问题时核心内存中的分页和为分页内存是否过小服务器Accept不成功应该不是端口问题
      

  37.   

    还有一个影响socket的就是,windows消息,如果发消息多,会阻塞WM_SOCKET_NOTIFY,会使socket阶段性阻塞的,所以单位秒不能有太多消息,否则socket消息阻塞。
      

  38.   

    Socekt Accept应该用的是物理内存中的核心内存
    LZ查看一下出问题时核心内存中的分页和为分页内存是否过小服务器Accept不成功应该不是端口问题
    分页内存是否过小----------------------多少才是为过少?
      

  39.   

    我最近也碰到这个情况,根据测试,如果CLIENT关闭Socket,Server不关,很快就不能连接了,如果Server关,C不关,则达到一定通断次数以后就不能连接了,超时或者拒绝连接,我想C不正常关闭应该很正常,特别在互联网上,如何解决呢?
      

  40.   

    关闭连接后,Windows本身自动释放socket就很慢的,linux下是自动释放的很快.
    若C和S已经连接,client关闭socket后会返回一个 空 给 server ,在server端作相应的关闭和释放处理.
    若C和S已经连接,server关闭socket后,client端相应的socket会自动被释放掉啊.
    我关闭连接一搬是 shutdown 然后 closesocket .
      

  41.   

    经我测试,不管怎样,SERVER和CLIENT都会释放掉SOCKET,因为在NETSTAT -NA的命令下始终看不到TIME_WAIT的记录,就算有,2、3分钟就会自动释放掉的。现在看来只有一种情况了,就是内存的问题了,是不是内存无法释放掉?连重起服务器程序都无法释放内存?
      

  42.   

    今天测试了一下,发觉这个问题可能和网络防火墙有关,在测试的时候,如果关闭网络防火墙,可以很顺利的进行几千次通断连接,而打开网络防火墙的情况下,在进行几十次连接甚至于几次连接以后,就可能导致服务端监听程序无响应。在查看防火墙记录时,发觉有服务端企图断开连接被拒绝的记录,因此,有可能是服务端SOCKET没有完全关闭导致拒绝连接,但是在这种情况下,如何不考虑防火墙的因素而完全关闭Socket?