注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

C#网络编程——对客户端队列的控制  

2015-12-01 10:59:03|  分类: 网络服务编程技术 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

C#网络编程——对客户端队列的控制

 

遇到的新问题是,程序在某种情况下会自动不断重连,原因尚未找到。

但其产生的结果就是,程序因为不断的重新连接,导致在Accept的时候:

“现在已经正在使用此 SocketAsyncEventArgs 实例进行异步套接字操作

猜测原因:

1、多个客户端的连接。导致程序无法使用。

2、会不会也需要每次重新连接时,创建新的RecSend SAEA

 

增大心跳控制时间从10秒到2分钟,两天未出现异常。但仍然会出现向一个IP客户端连续发送大量心跳的现象,不知道原因。猜测有两种:

1、客户端队列删除逻辑或者删除方式有问题,导致未删除当前连接客户端队列。

2、数据传递不对,始终是一个。

 

经过分析日志,发现了问题,第一,客户端有六个在一个客户机上打开。其它的也有几个的。而在走查程序时发现,对心跳的发送和接收是按照SOCKET来判定的,但是对心跳的计数器的处理,则是按照IP地址处理的。(当时决定的是一个客户机只能起一个客户端,所以偷懒了,结果???汗一个。)结果就是,六个客户端会不停的在心跳三次后依次被干掉,然后启动重连,这样就导致了上面的问题,不断的定时重连。所以不能光听工程人员讲,要实际去现场看。

现在修改了客户端为单实例,结果跑了三天了,没有发现什么问题。而且重连都没有,也证明了客户说的网络还是很好的。

至于出现上面红色的Bug的原因,是在队列中只开辟了十个左右,最大二十个,反复的重连会造成不断的重用这些SAEA,而C#不会即时的释放那些无用的SAEA,导致出现这个BUG,引起程序崩溃,代码是在此处:

                lock (sc)

                {

                    //继续接收

                    bRecv = sc.CurSocket.ReceiveAsync(sc.RecvEventArgs);

                }

红色部分的定义如下:

public SocketAsyncEventArgs RecvEventArgs { get; private set; }

说一说这几天的解决过程:

1、首先考虑是不是Accept是不是也要每次重新创建SAEA,经过反复查找资料和看别人的代码,发现这个确实是不用。改了后又改了回来,没有去现场上试。其实除了多浪费一些SAEA没别的作用。

2、针对错误的地点,将SAEA的客户端封装队列从10变成了一1000,目的是为了测试,虽然这样付出的代价比较大。但毕竟是为了看是不是这个原因。回头测试完成后可以回退到100左右,甚至更少,当然这个看你的连接环境了,如果一直有上千个在上面,就得创建千个了。

3、增加了大量的测试。

4、将心跳改成了10分钟,则三次半小时后才会引起重连,主要是想减少重连对服务端的压力,可是没想到改成单实例后,不会有前面提到的多个客户端了,心跳引起的重连自然也就没有了。

5、将重点放到了重连的控制上:

        private void ConnectServer()

        {

           // _client.ReConEvent.Reset();//正常AutoResetEvent是不需要Reset的,但可能业务逻辑或者控制上的需要,这里增加了Reset。有时间梳理一下应用,看可否修改。2014-12-01

            TransEventArgs args = new TransEventArgs();

            //如果超时则继续重连:重连时间定为0.5分钟

            do

            {

                _client.Start(_np, _tsd);

 

                //重连时间最长控制在1小时一次。2015-11-23

                //s_reConCount++;

                //if (s_reConCount > 19)

                //{

                //    s_reConCount = 20;

                //}

              

                //args.Obj = "进入重连的第" + s_reConCount.ToString()+"";

                //args.Type = 9;

                //this.Handle(this,args);

            } while (!_client.ReConEvent.WaitOne(1000 * 30 * s_reConCount)); //30s改为3分钟 gqy11.13  (1000 *30)); 11@23 增加回退加倍* 6

 

            //接收到信号则退出线程

            //s_Num--;

            //s_reConCount = 1;

            //this._reconThreadStatus = true;//退出前为下一次重连置位

           

            args.Type = 9;

            args.Obj = "已经退出重连网络-----------";

            this.Handle(this,args);

            return;

        }

采用了回退机制,但是同样的的原因,修正了多个客户端后,程序稳定了。其实这个坑儿不能说全怪别人,对客户端的判断明显着有一个考虑不同的地方(只判断IP没有判断Port),因此引起心跳的处理异常,进尔引起重连和服务端的崩溃,也算是自己挖坑自己填。怨不得别人啊。

在前面不断的加锁控制SendRecv,机制是正确的,但是没有正确的处理错误的位置,所以也没有产生比较明显的效果。

  评论这张
 
阅读(270)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017