当前位置:首页 > 网络编程 > WEB编程 > ASP.net >  .NET下可复用的TCP通信层实现之TCP组件(5)

 .NET下可复用的TCP通信层实现之TCP组件(5)

点击次数:16 次 发布日期:2008-11-26 12:27:46 作者:源代码网
源代码网推荐      5.异步Tcp组件实现
源代码网推荐  
源代码网推荐    这种方式的主要思想是:当一个新的Tcp连接建立时,就在该连接上发送一个异步接收的请求(BeginRead),并在异步回调中处理该请求,当请求处理完毕,再次发送异步接收请求,如此循环下去。异步接收启用的是系统默认线程池中的线程,所以,在异步Tcp组件中不用显式管理工作线程。异步Tcp组件的实现相对于完成端口模型而言简单许多,也单纯一些,不用管理请求队列,不需使用工作者线程等等。但是,相比于完成端口模型,其也有明显的缺陷:一个Tcp连接绑定到了一个线程,即使这个线程是后台线程池中的。如果用户数量巨大,这对性能是极其不利的;而完成端口模型,则可以限定工作者线程的个数,并且可以根据应用的类型进行灵活调节。
源代码网推荐  
源代码网推荐    异步Tcp组件实现源码。
源代码网推荐  
源代码网推荐    异步Tcp组件
源代码网推荐  
源代码网推荐  1/**//// <summary>
源代码网推荐  2 /// AsynTcp 异步Tcp组件。
源代码网推荐  3 /// </summary>
源代码网推荐  4 public class AsynTcp :ITcp
源代码网推荐  5 {
源代码网推荐  6 members#region members
源代码网推荐  7 private const int BufferSize = 1024 ;
源代码网推荐  8
源代码网推荐  9 private IXTcpListener xtcpListener = null ;
源代码网推荐  10 private ITcpReqStreamDispatcher messageDispatcher = null ;
源代码网推荐  11 private ContextKeyManager contextKeyMgr = new ContextKeyManager() ;
源代码网推荐  12 private bool stateIsStop = true ;
源代码网推荐  13 private bool validateRequest = false ;
源代码网推荐  14 private int curPort = 8888 ;
源代码网推荐  15 #endregion
源代码网推荐  16
源代码网推荐  17
源代码网推荐  18 public AsynTcp()
源代码网推荐  19 {
源代码网推荐  20
源代码网推荐  21 }
源代码网推荐  22
源代码网推荐  23 INet 成员#region INet 成员
源代码网推荐  24
源代码网推荐  25 public event CallBackDynamicMessage DynamicMsgArrived;
源代码网推荐  26
源代码网推荐  27 public NetAddinType GetProtocalType()
源代码网推荐  28 {
源代码网推荐  29
源代码网推荐  30 return NetAddinType.Tcp;
源代码网推荐  31 }
源代码网推荐  32
源代码网推荐  33 InitializeAll ,UnitializeAll#region InitializeAll ,UnitializeAll
源代码网推荐  34 public void InitializeAll(IReqestStreamDispatcher i_dispatcher, int port, bool userValidated)
源代码网推荐  35 {
源代码网推荐  36 this.messageDispatcher = i_dispatcher as ITcpReqStreamDispatcher;
源代码网推荐  37 if(this.messageDispatcher == null)
源代码网推荐  38 {
源代码网推荐  39 throw new Exception("Can"t convert IReqestStreamDispatcher to ITcpReqStreamDispatcher in CompletePortManager.InitializeAll method ! ") ;
源代码网推荐  40 }
源代码网推荐  41
源代码网推荐  42 this.curPort = port ;
源代码网推荐  43 this.validateRequest = userValidated ;
源代码网推荐  44
源代码网推荐  45 this.InitializeAll() ;
源代码网推荐  46 }
源代码网推荐  47
源代码网推荐  48 public void InitializeAll()
源代码网推荐  49 {
源代码网推荐  50 this.xtcpListener = new XTcpListener(this.curPort) ;
源代码网推荐  51 this.xtcpListener.TcpConnectionEstablished += new CBackUserLogon(xtcpListener_TcpConnectionEstablished);
源代码网推荐  52 this.xtcpListener.DynamicMsgArrived += new CallBackDynamicMsg(this.PutoutDynamicMsg) ;
源代码网推荐  53 this.contextKeyMgr.StreamCountChanged += new CallBackCountChanged(this.OnStreamCountChanged) ;
源代码网推荐  54 }
源代码网推荐  55
源代码网推荐  56 public void UnitializeAll()
源代码网推荐  57 {
源代码网推荐  58 this.Stop() ;
源代码网推荐  59 this.xtcpListener.ExitListenThread() ;
源代码网推荐  60
源代码网推荐  61 //将事件容器清空==》防止外部框架再多次初始化的过程中将一个事件预定多次
源代码网推荐  62 this.ConnectionCountChanged = null ;
源代码网推荐  63 this.DynamicMsgArrived = null ;
源代码网推荐  64 this.ServiceCommitted = null ;
源代码网推荐  65 this.SomeOneConnected = null ;
源代码网推荐  66 this.SomeOneDisConnected = null ;
源代码网推荐  67 this.UserAction = null ;
源代码网推荐  68 }
源代码网推荐  69
源代码网推荐  70 #endregion
源代码网推荐  71
源代码网推荐  72 Start ,Stop#region Start ,Stop
源代码网推荐  73 public void Start()
源代码网推荐  74 {
源代码网推荐  75 if(this.stateIsStop)
源代码网推荐  76 {
源代码网推荐  77 this.xtcpListener.Start() ;
源代码网推荐  78 this.stateIsStop = false ;
源代码网推荐  79 }
源代码网推荐  80 }
源代码网推荐  81
源代码网推荐  82 public void Stop()
源代码网推荐  83 {
源代码网推荐  84 if(this.stateIsStop)
源代码网推荐  85 {
源代码网推荐  86 return ;
源代码网推荐  87 }
源代码网推荐  88
源代码网推荐  89 this.stateIsStop = true ;
源代码网推荐  90 this.xtcpListener.Stop() ;
源代码网推荐  91
源代码网推荐  92 //关闭所有连接
源代码网推荐  93 int count = 0 ;
源代码网推荐  94 while(! this.contextKeyMgr.IsAllStreamSafeToStop()) //等待所有流到达停止安全点
源代码网推荐  95 {
源代码网推荐  96 Thread.Sleep(200) ;
源代码网推荐  97 if(10 == count++)
源代码网推荐  98 {
源代码网推荐  99 break ;
源代码网推荐  100 }
源代码网推荐  101 }
源代码网推荐  102 this.contextKeyMgr.DisposeAllContextKey() ;
源代码网推荐  103 }
源代码网推荐  104 #endregion
源代码网推荐  105
源代码网推荐  106 #endregion
源代码网推荐  107
源代码网推荐  108 ITcpEventList 成员#region ITcpEventList 成员
源代码网推荐  109
源代码网推荐  110 public event EnterpriseServerBase.Network.CallBackForTcpUser2 SomeOneConnected;
源代码网推荐  111
源代码网推荐  112 public event EnterpriseServerBase.Network.CallBackForTcpMonitor ServiceCommitted;
源代码网推荐  113
源代码网推荐  114 public event EnterpriseServerBase.Network.CallBackForTcpCount ConnectionCountChanged;
源代码网推荐  115
源代码网推荐  116 public event EnterpriseServerBase.Network.CallBackForTcpUser1 SomeOneDisConnected;
源代码网推荐  117
源代码网推荐  118 public event EnterpriseServerBase.Network.CallBackForTcpUser UserAction;
源代码网推荐  119
源代码网推荐  120 #endregion
源代码网推荐  121
源代码网推荐  122 ITcpClientsController 成员#region ITcpClientsController 成员
源代码网推荐  123
源代码网推荐  124 public bool SynRecieveFrom(int ConnectID ,byte[] buffer, int offset, int size ,out int readCount)
源代码网推荐  125 {
源代码网推荐  126 readCount = 0 ;
源代码网推荐  127 ISafeNetworkStream netStream = this.contextKeyMgr.GetNetStream(ConnectID) ;
源代码网推荐  128 if(netStream == null)
源代码网推荐  129 {
源代码网推荐  130 return false ;
源代码网推荐  131 }
源代码网推荐  132
源代码网推荐  133 readCount = netStream.Read(buffer ,offset ,size) ;
源代码网推荐  134
源代码网推荐  135 return true ;
源代码网推荐  136 }
源代码网推荐  137
源代码网推荐  138 public void SendData(int ConnectID, byte[] data)
源代码网推荐  139 {
源代码网推荐  140 this.SendData(ConnectID ,data ,0 ,data.Length) ;
源代码网推荐  141 }
源代码网推荐  142
源代码网推荐  143 public void SendData(int ConnectID, byte[] data ,int offset ,int size)
源代码网推荐  144 {
源代码网推荐  145 if((data == null) || (data.Length == 0) || (offset <0) ||(size <0) || (offset+size > data.Length))
源代码网推荐  146 {
源代码网推荐  147 return ;
源代码网推荐  148 }
源代码网推荐  149
源代码网推荐  150 ISafeNetworkStream netStream = this.contextKeyMgr.GetNetStream(ConnectID) ;
源代码网推荐  151 if(netStream == null)
源代码网推荐  152 {
源代码网推荐  153 return ;
源代码网推荐  154 }
源代码网推荐  155
源代码网推荐  156 netStream.Write(data ,offset ,size) ;
源代码网推荐  157 }
源代码网推荐  158
源代码网推荐  159 public void DisposeOneConnection(int connectID, DisconnectedCause cause)
源代码网推荐  160 {
源代码网推荐  161 this.DisposeOneConnection(connectID) ;
源代码网推荐  162
源代码网推荐  163 if(this.SomeOneDisConnected != null)
源代码网推荐  164 {
源代码网推荐  165 this.SomeOneDisConnected(connectID , cause) ;
源代码网推荐  166 }
源代码网推荐  167
源代码网推荐  168 this.ActivateUserActionEvent(connectID ,TcpUserAction.Exit) ;
源代码网推荐  169 }
源代码网推荐  170
源代码网推荐  171 #endregion
源代码网推荐  172
源代码网推荐  173 ITcp 成员#region ITcp 成员
源代码网推荐  174 public int ConnectionCount
源代码网推荐  175 {
源代码网推荐  176 get
源代码网推荐  177 {
源代码网推荐  178 return this.contextKeyMgr.ConnectionCount ;
源代码网推荐  179 }
源代码网推荐  180 }
源代码网推荐  181
源代码网推荐  182 #endregion
源代码网推荐  183
源代码网推荐  184 private#region private
源代码网推荐  185
源代码网推荐  186 ActivateUserActionEvent#region ActivateUserActionEvent
源代码网推荐  187 private void ActivateUserActionEvent(int ConnectID ,TcpUserAction action)
源代码网推荐  188 {
源代码网推荐  189 if(this.UserAction != null)
源代码网推荐  190 {
源代码网推荐  191 this.UserAction(ConnectID ,action) ;
源代码网推荐  192 }
源代码网推荐  193 }
源代码网推荐  194 #endregion
源代码网推荐  195
源代码网推荐  196 DisposeOneConnection#region DisposeOneConnection
源代码网推荐  197 /**//// <summary>
源代码网推荐  198 /// DisposeOneConnection 主要由用户管理模块调用--当无法检测到掉线情况时,该方法保证资源被释放
源代码网推荐  199 /// </summary>
源代码网推荐  200 private void DisposeOneConnection(int connectID)
源代码网推荐  201 {
源代码网推荐  202 this.contextKeyMgr.RemoveContextKey(connectID) ;
源代码网推荐  203 }
源代码网推荐  204 #endregion
源代码网推荐  205
源代码网推荐  206 xtcpListener_TcpConnectionEstablished#region xtcpListener_TcpConnectionEstablished
源代码网推荐  207 private void xtcpListener_TcpConnectionEstablished(NetworkStream stream)
源代码网推荐  208 {
源代码网推荐  209 ISafeNetworkStream safeStream = new SafeNetworkStream(stream) ;
源代码网推荐  210
源代码网推荐  211 ContextKey key = new ContextKey(safeStream ,AsynTcp.BufferSize) ;
源代码网推荐  212 key.ResetBuffer(null) ;
源代码网推荐  213 this.contextKeyMgr.InsertContextKey(key) ;
源代码网推荐  214 int connectID = key.NetStream.GetHashCode() ;
源代码网推荐  215
源代码网推荐  216 if(this.SomeOneConnected != null)
源代码网推荐  217 {
源代码网推荐  218 this.SomeOneConnected(connectID) ;
源代码网推荐  219 }
源代码网推荐  220 this.ActivateUserActionEvent(connectID ,TcpUserAction.Logon) ;
源代码网推荐  221
源代码网推荐  222 key.IsFirstMsg = true ;
源代码网推荐  223 this.RecieveDataFrom(key) ;
源代码网推荐  224 }
源代码网推荐  225 #endregion
源代码网推荐  226
源代码网推荐  227 PutoutDynamicMsg#region PutoutDynamicMsg
源代码网推荐  228 private void PutoutDynamicMsg(string msg)
源代码网推荐  229 {
源代码网推荐  230 if(this.DynamicMsgArrived != null)
源代码网推荐  231 {
源代码网推荐  232 this.DynamicMsgArrived(msg) ;
源代码网推荐  233 }
源代码网推荐  234 }
源代码网推荐  235 #endregion
源代码网推荐  236
源代码网推荐  237 OnStreamCountChanged#region OnStreamCountChanged
源代码网推荐  238 private void OnStreamCountChanged(int count)
源代码网推荐  239 {
源代码网推荐  240 if(this.ConnectionCountChanged != null)
源代码网推荐  241 {
源代码网推荐  242 this.ConnectionCountChanged(count) ;
源代码网推荐  243 }
源代码网推荐  244 }
源代码网推荐  245 #endregion
源代码网推荐  246
源代码网推荐  247 RecieveDataFrom#region RecieveDataFrom
源代码网推荐  248 private void RecieveDataFrom(ContextKey key)
源代码网推荐  249 {
源代码网推荐  250 key.StreamState = NetStreamState.Reading ;
源代码网推荐  251 key.NetStream.BeginRead(key.Buffer ,key.StartOffsetForRecieve ,key.MaxRecieveCapacity ,new AsyncCallback(this.ServeOverLap) ,key) ;
源代码网推荐  252
源代码网推荐  253 }
源代码网推荐  254 #endregion
源代码网推荐  255
源代码网推荐  256 ServeOverLap#region ServeOverLap
源代码网推荐  257 private void ServeOverLap(IAsyncResult ar)
源代码网推荐  258 {
源代码网推荐  259 ContextKey key = (ContextKey)ar.AsyncState ;
源代码网推荐  260 int streamHashCode = key.NetStream.GetHashCode() ; //是SafeNetworkStream的hashcode
源代码网推荐  261
源代码网推荐  262 try
源代码网推荐  263 {
源代码网推荐  264 key.BytesRead = key.NetStream.EndRead(ar) ;
源代码网推荐  265
源代码网推荐  266 if(! this.CheckData(key))
源代码网推荐  267 {
源代码网推荐  268 return ;
源代码网推荐  269 }
源代码网推荐  270
源代码网推荐  271 //处理请求
源代码网推荐  272 byte[] leftData = null ;
源代码网推荐  273 ArrayList repondList = this.messageDispatcher.DealRequestMessage(key.RequestData ,out leftData , ref key.Validation) ;
源代码网推荐  274
源代码网推荐  275 if(this.validateRequest)
源代码网推荐  276 {
源代码网推荐  277 if(key.Validation.gotoCloseConnection)
源代码网推荐  278 {
源代码网推荐  279 this.DisposeOneConnection(streamHashCode ,key.Validation.cause) ;
源代码网推荐  280 }
源代码网推荐  281 }
源代码网推荐  282
源代码网推荐  283 key.StreamState = NetStreamState.Writing ;
源代码网推荐  284 if(repondList!= null && (repondList.Count != 0))
源代码网推荐  285 {
源代码网推荐  286 foreach(object obj in repondList)
源代码网推荐  287 {
源代码网推荐  288 byte[] respond_stream = (byte[])obj ;
源代码网推荐  289 key.NetStream.Write(respond_stream ,0 ,respond_stream.Length) ;
源代码网推荐  290 if(this.ServiceCommitted != null)
源代码网推荐  291 {
源代码网推荐  292 RespondInformation info = new RespondInformation() ;
源代码网推荐  293 info.ConnectID = streamHashCode ;
源代码网推荐  294 info.ServiceKey = this.messageDispatcher.GetServiceKey(respond_stream) ;
源代码网推荐  295 info.repondData = respond_stream ;
源代码网推荐  296 this.ServiceCommitted(info) ;
源代码网推荐  297 }
源代码网推荐  298
源代码网推荐  299 this.ActivateUserActionEvent(streamHashCode ,TcpUserAction.FunctionAccess) ;
源代码网推荐  300 }
源代码网推荐  301 }
源代码网推荐  302
源代码网推荐  303 if(key.IsFirstMsg)
源代码网推荐  304 {
源代码网推荐  305 if(repondList == null || (repondList.Count == 0)) //表示第一条消息还未接收完全
源代码网推荐  306 {
源代码网推荐  307 key.IsFirstMsg = true ;
源代码网推荐  308 }
源代码网推荐  309 else
源代码网推荐  310 {
源代码网推荐  311 key.IsFirstMsg = false ;
源代码网推荐  312 }
源代码网推荐  313 }
源代码网推荐  314
源代码网推荐  315 key.StreamState = NetStreamState.Idle ;
源代码网推荐  316
源代码网推荐  317 key.ResetBuffer(leftData) ;
源代码网推荐  318
源代码网推荐  319 if(! this.stateIsStop)
源代码网推荐  320 {
源代码网推荐  321 //继续接收请求
源代码网推荐  322 this.RecieveDataFrom(key) ;
源代码网推荐  323 }
源代码网推荐  324 else //停止服务
源代码网推荐  325 {
源代码网推荐  326 this.DisposeOneConnection(streamHashCode ,DisconnectedCause.ServerStopped) ;
源代码网推荐  327 }
源代码网推荐  328 }
源代码网推荐  329 catch(Exception ee)
源代码网推荐  330 {
源代码网推荐  331 if(ee is System.IO.IOException) //正在读写流的时候,连接断开
源代码网推荐  332 {
源代码网推荐  333 this.DisposeOneConnection(streamHashCode ,DisconnectedCause.ServerStopped) ;
源代码网推荐  334 }
源代码网推荐  335
源代码网推荐  336 ee = ee ;
源代码网推荐  337 }
源代码网推荐  338 }
源代码网推荐  339 #endregion
源代码网推荐  340
源代码网推荐  341 CheckData#region CheckData
源代码网推荐  342 private bool CheckData(ContextKey key)
源代码网推荐  343 {
源代码网推荐  344 int streamHashcode = key.NetStream.GetHashCode() ;
源代码网推荐  345 if(this.stateIsStop)
源代码网推荐  346 {
源代码网推荐  347 this.DisposeOneConnection(streamHashcode ,DisconnectedCause.ServerStopped) ;
源代码网推荐  348 return false;
源代码网推荐  349 }
源代码网推荐  350
源代码网推荐  351 if(key.BytesRead == 0) //表示客户端掉线或非正常关闭连接
源代码网推荐  352 {
源代码网推荐  353 this.DisposeOneConnection(streamHashcode ,DisconnectedCause.LineOff) ;
源代码网推荐  354 return false ;
源代码网推荐  355 }
源代码网推荐  356
源代码网推荐  357 if(key.BytesRead == 8)//表示客户端正常关闭连接
源代码网推荐  358 {
源代码网推荐  359 string ss = System.Text.Encoding.BigEndianUnicode.GetString(key.Buffer ,0 ,8) ;
源代码网推荐  360 this.DisposeOneConnection(streamHashcode ,DisconnectedCause.LineOff) ;
源代码网推荐  361 return false;
源代码网推荐  362 }
源代码网推荐  363
源代码网推荐  364 return true ;
源代码网推荐  365 }
源代码网推荐  366 #endregion
源代码网推荐  367 #endregion
源代码网推荐  368
源代码网推荐  369 INet 成员#region INet 成员
源代码网推荐  370
源代码网推荐  371 public IReqestStreamDispatcher Dispatcher
源代码网推荐  372 {
源代码网推荐  373 set
源代码网推荐  374 {
源代码网推荐  375 this.messageDispatcher = (ITcpReqStreamDispatcher)value ;
源代码网推荐  376 }
源代码网推荐  377 }
源代码网推荐  378
源代码网推荐  379 public int Port
源代码网推荐  380 {
源代码网推荐  381 set
源代码网推荐  382 {
源代码网推荐  383 this.curPort = value ;
源代码网推荐  384 }
源代码网推荐  385 get
源代码网推荐  386 {
源代码网推荐  387 return this.curPort ;
源代码网推荐  388 }
源代码网推荐  389 }
源代码网推荐  390
源代码网推荐  391 public bool UserValidated
源代码网推荐  392 {
源代码网推荐  393 set
源代码网推荐  394 {
源代码网推荐  395 this.validateRequest = value ;
源代码网推荐  396 }
源代码网推荐  397 }
源代码网推荐  398
源代码网推荐  399 #endregion
源代码网推荐  400 }
源代码网推荐  
源代码网推荐    今天介绍了Tcp通信层中的核心――Tcp组件,仅仅复用Tcp组件已经能为我们省去很多麻烦了,如果想进行更高层次的复用――整个Tcp通信层的复用,请关注本篇的续文。
源代码网推荐  
源代码网推荐  
源代码网推荐    做人要厚道,请注明转自酷网动力(www.ASPCOOL.COM)。
源代码网推荐


源代码网供稿.
网友评论 (0)
会员中心
网络编程
本站推荐
网络编程之精华