首页 > 代码库 > Socket通信中的 BeginReceive与EndReceive

Socket通信中的 BeginReceive与EndReceive

BeginReceive 与endReceive 必须成对出现,如果BeginReceive没有及时调用endReceive,可能会出现数据被从buffer中读取二次,如果在下面这行代码下面加入别的代码

 就会出现被处理二次的结果 如下

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public void BeginReceive(SessionListner listner)
        {
            if (listner.State != TSessionState.Active)
            {
                return;
            }
            try
            {
                int bufferOffset = this.BufferManager.GetReceivevBufferOffset(m_bufferBlockIndex);
                WorkSocket.BeginReceive(this.BufferManager.ReceiveBuffer, bufferOffset, this.BufferManager.ReceiveBufferSize, SocketFlags.None, this.EndReceiveDatagram, listner);
                listner.Receive();
            }
 
            catch (Exception err)  // 读 Socket 异常,准备关闭该会话
            {
                listner.DisconnectType = TDisconnectType.Exception;
                listner.State = TSessionState.Inactive;//这个客户状态不活动了
                //说明发送端口被异常关闭了
                this.OnSessionReceiveException(listner, err);
            }
        }

 上面的  listner.Receive();处理缓存数据方法

 然后再执行

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
private void EndReceiveDatagram(IAsyncResult iar)
       {
           SessionListner listner = (iar.AsyncState as SessionListner);
 
           if (listner.State != TSessionState.Active)
           {
               return;
           }
           try
           {
               int cr = WorkSocket.EndReceive(iar);
               Console.WriteLine(cr);
               if (cr == 0)
               {
                   listner.DisconnectType = TDisconnectType.Normal;
                   listner.State = TSessionState.Inactive;
                   //被关闭了,需要及时关闭
               }
               else
               {
                   listner.LastSessionTime = DateTime.Now;
                   this.BufferManager.RealReceiveSize = cr;
                    this.BeginReceive(listner);
               }
           }

 就出现被二次处理的问题,分析得出:1,在第一次读取完就处理缓冲数据,2同时进入了EndReceiveDatagram方法,再一次时进入BeginReceive方法 ,但没有处理完第一次缓存数据,就可能导致处理数据不正确。

需要改成:EndReceiveDatagram中处理数据

 else
                {
                    listner.LastSessionTime = DateTime.Now;
                    this.BufferManager.RealReceiveSize = cr;
                    listner.Receive();
                   
                    this.BeginReceive(listner);
                }

总结:处理数据永远需要放到接收后处理,BeginReceive在永远不断的起线程,而endReceive在不断的帮它完成回收和结束工作。在Begin中下面放执行代码有可能有一定问题。也就是在没有end的时候,没有阻塞后,再操作共享变量有一定问题,所以begin与end同时操作共享对象或变量时时一定要end之后。无论socket还是一般的异步委托方法。