如果客户端禁用网络或者拔网线,服务器一切如常,在线列表也会多一个失效的客户端。如果客户端是结束进程或者明确关闭,服务器会收到空信息或者捕获异常,可以处理。
现在想请问第一种情况如何处理,就是加一些特殊处理,可以及时释放连接和相关资源,把失效的连接处理掉我的做法是开一个维护线程,某个Socket多少分钟内没有向服务器发任何数据(需要记录每个客户端最后一次向服务器发送数据的时间)的话,就把它断掉,释放资源。
这样可以达到目的,但维护线程需要占用服务器资源,并且遍历时要对在线列表加锁,很浪费资源请教各位朋友,有没有更好的做法呢?

解决方案 »

  1.   

    http://blog.csdn.net/wzd24/archive/2007/04/13/1564112.aspx看看我这篇文章,讲的就是这个。
      

  2.   

    有,我的做法是在接受回调里捕捉异常
    catch (SocketException ex)
                {
                    if (ex.ErrorCode == 10054)
                    {
                        CloseSocket(cl);
                    }
                }
    可以在这里面处理
      

  3.   

    想顺便再请教老大一个问题,
    如果有服务器向客户端发送文件之类的协议,一般客户端先发送请求,然后服务器把文件拆分成多个包(GPRS网络通讯时,包一般不超过1K),发送给客户端
    请问:此时服务器端的重发机制要怎么做呢?需要在服务器端做重发么?还是说只在客户端做不好意思,一个贴问两个问题,不够再加分
      

  4.   

    To yf370768770:
    如果是客户端正常关闭或者结束进程,服务端一般可以收到空信息,或者在发送、接收时出现异常,这样你的方法是可以处理的
    加入是客户端断电、禁用网络、拔网线这类情况,服务器是没有任何反应的
      

  5.   

    wzd24的方法是可行的,但不可避免也会造成性能的损失:(1)在短暂的故障期间,它们可能引起一个良好连接(good connection)被释放(dropped),(2)它们消费了不必要的带宽,(3)在以数据包计费的互联网上它们(额外)花费金钱但是对于需要实时知道客户端状态的情况,这种机制应该也是必须的呵呵,我原来用的做法太落后了,多谢wzd24
      

  6.   

    又加了20分后面补充的问题是这样的:
    由于GRPS网络的不可靠性,传输协议把所有的包都定在1K一下(保证它不会再在传输层拆分),这样客户端只要能收到,就是正确的了,因为TCP是保证正确到达的,只有一个包,那也肯定是完整的。现在问题是,如果丢包了怎么办?也就是说客户端什么都没收到,还在等着呢如果是客户端主动发起的请求,每收到回复肯定要重发请求,重发机制尽量做到客户端。对于传文件,是服务端发给客户端的,客户端每收到一个包都会做出应答。
    假如一个文件分为100个包,服务器从第一个包开始发,收到客户端回复后才发第二包(也可以一次发10个之类的滑动窗口,但也有这个问题),加入第二个包客户端没收到,是不是要重发呢
      

  7.   

    请教wzd24:
    你介绍的文章里
    IOControlCode.KeepAliveValues是什么啊
      

  8.   

    To yf370768770:
    如果是客户端正常关闭或者结束进程,服务端一般可以收到空信息,或者在发送、接收时出现异常,这样你的方法是可以处理的
    加入是客户端断电、禁用网络、拔网线这类情况,服务器是没有任何反应的
    ------------------------------------------------------------------------
    这种情况我还没试过,以后试了看看!!
      

  9.   

    比如说有没有timeout之类的属性,设置一下,不用在应用层做
    总是感觉在应用层做轮训队性能影响太大:要频繁轮训,又要对客户端在线列表加锁
      

  10.   

    Socket的同步Receive可以设置TimeOut。
      

  11.   

    遇到了极为郁闷的问题:
    昨天晚上开了服务器,一个终端客户端连了又关机又连,多次后,在线列表上已经有多个重复的客户端了。假如没有按wzd24大侠的方法更改默认设置,那么应该在2小时多之后,失效的客户端会被清除掉
    郁闷的是,早上过来那些客户端还在列表上!而且昨晚终端已经关机了!用netstat看了一下,连到我的服务器端口的确实只有一个连接。
    服务器的默认设置是用wzd24的方法改过的,代码如下:
    对每一个连上来的客户端设置(2003写的,没有那个枚举值):
    uint dummy = 0;
    byte[] inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];
    BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0);
    BitConverter.GetBytes((uint)180000).CopyTo(inOptionValues, Marshal.SizeOf(dummy));
    BitConverter.GetBytes((uint)15000).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2);
    const uint SIO_KEEPALIVE_VALS = 0x80000000 | 0x18000000 | 4;
    unchecked
    {
    int sio = (int)SIO_KEEPALIVE_VALS;
    client.IOControl(sio, inOptionValues, null);//2550136836
    }3分钟后开始检测,每15秒发送一次
    这个设置是管用的,我早上过来后还试了一次,连一个PC客户端,然后把自己的网线拔掉,再看服务器,大概5、6分钟后,失效的客户端会被清掉现在郁闷的是,为什么终端客户端的不会,而且还是昨天晚上都失效掉的