当前位置: 代码迷 >> C# >> C# BeginReceive,该如何处理
  详细解决方案

C# BeginReceive,该如何处理

热度:461   发布时间:2016-05-05 05:17:43.0
C# BeginReceive
目前是接收一次处理一次,当对方发动数据大于我定义的长度1024后,后面的数据就错了;
想修改为全部接收完再做处理,应该怎么修改???

代码如下:
  public void ReceivedCallback(IAsyncResult ar)
  {
            try
            {
                StateObjectClass state = (StateObjectClass)ar.AsyncState;
                Socket handler = state.workSocket;
                if (handler == null) return;

                if (handler.Connected != true)
                {
                    handler.Close();
                    //客户端退出
                    //...
                    return;
                }

                int bytesRead = handler.EndReceive(ar);
                state.bytesRead = bytesRead;

                if (bytesRead != 0)
                {
     //CommAction 方法内容: a.截取所发指令的前面几个字节分析是不是要求的指令
                   //里面有一个  state.packetBuff = state.buffer.Take(bytesRead).ToArray();的操作    
                    state = CommAction(state);
                   
                    if (state.CommandString != "")
                    //处理指令

                    //回调
                    handler.BeginReceive(state.buffer, 0, StateObjectClass.BufferSize, 0,
                        new AsyncCallback(ReceivedCallback),
                        state);
                }
                else
                {
                    handler.Close(); //客户端退出
                    //...
                }
            }
            catch (SocketException ex)
            {
                if (ex.ErrorCode == 10054) //客户端关闭连接
                {
                    //...
                }
            }
            catch (Exception ex)
            {
   //...
            }
        }

------解决思路----------------------
要么把你的1024改成足够大,能够一次性接收到全部的数据不要截断
要么定义好通信协议,以什么开始,以什么结束,或者先发个较短的包过来告诉后面的包总长度
否则你怎么知道什么时候算接收完了?
------解决思路----------------------
如果你想把多次收到的数据先拼接到一起
一样还是需要另一个足够大的数组来存放这个数据啊
------解决思路----------------------
你的Socket是长连接还是短连接?
如果是长连接,你没办法确定报文有没有传输完,只能根据报文包长度进行截取。
短连接的话,根据你的通讯协议,定义适当长度的缓存数组。
------解决思路----------------------
引用:
就是内存问题,能有其它方法暂时不定义大的,因为其它指令都很小,16G内存
效率我没有实际测试,所以不敢肯定影响有多大,或许是微乎其微吧!

不定义大的你就必须知道长度,然后循环接收,直到长度满足,或者对方发送完成会关闭通道,不然你无法知道什么时候才算收完
------解决思路----------------------
你原先代码中:
if?(state.CommandString?!=?"")
//处理指令

这个处理指令部分修改下,不要直接处理指令,而是先将接收到的内容存到队列中,例如
全局定义一个List<byte[]> buffers = new List<byte[]>();
之后if (bytesRead != 0)时
if?(state.CommandString?!=?"" && buffers.Count>0)
{
    //把buffers里面原有的数组列表拼接处理为一个命令,并执行
    buffers.Clear(); //清空buffers
}
buffers.Add(state.packetBuff);//写新命令数据进buffers队列。

else时
if?(buffers.Count>0)
{
    //把buffers里面原有的数组列表拼接处理为一个命令,并执行
    buffers.Clear(); //清空buffers
}

------解决思路----------------------
引用:
字节数组可以用Concat拼接,但回调里面是不是应该是线程安全方法,直接定义全局变量不妥吧
如果同一时间只有一个线程可以访问这个方法那么异步又是没有意义了,指令会一个一个串行不是我想要的

我学习的不好,还在看

我的疏忽,没考虑多线程的情况,你可以修改StateObjectClass类的定义,将那个List<byte[]> buffers作为一个属性定义在类内部,通过state传递到下次操作中累计即可。
  相关解决方案