C# SOCKET 粘包、断包处理(一)

1 篇文章 0 订阅
1 篇文章 0 订阅
    一直是用JAVA,关于SOCKET方面,JAVA有一个不错的框架MINA2,对于粘包、断包的处理有这个良好的处理,个人需要写的代码并不太多。
    而C#、因为了解不多,也没去看第三方的SOCKET框架,所以只好根据MSDN提示,自己去实现了。
    
    在代码之前,我们先说说处理中会碰到的情况如何:
    1、先假设数据包的格式如下:
       包长度(4字节)MD5签名(32字节)客户端ID(5字节)数据类型(5字节)数据ID(32字节)数据内容(动态长度、不固定)
       |--------------------------------包头78字节--------------------------------------|------包体-----------------|
    
    2、接收数据包时,可能会遇到的问题(假设,每次接收的缓冲区为1024字节):
        A、一次就接收到一个完整的包,也即此完整的数据包长度少于1024字节,并且无其他数据包的数据与这个包的数据粘在一起;
            也即,此数据包的数据情况如下:
            缓冲区:|--------------------------1024字节----------------------|
            数据包:|------数据包1------|






B、一个接收的数据中有几个包的数据粘合在一起,也即如下:
                缓冲区:|--------------------------1024字节----------------------|
                数据包:|------数据包1数据包2数据包3...数据包N------|                //N个数据包数据链接在一起,但整体不超过1024个字节

        或者数据包:|------数据包1数据包2数据包3.....数据包N(部分数据)-----|   //N个数据包数据链接在一起,最后一个包的数据为此数据包的一部分数据




C、一个接收的数据为一个包的部分数据,也即此包的数据长度大于1024个字节,也即如下:
    缓冲区:|--------------------------1024字节----------------------|
  数据包1:|-------------数据1(某数据包的部分数据)----------------|    //某个数据包的部分数据
  数据包2:|-------------数据2(某数据包的部分数据)----------------|    //某个数据包的部分数据
           ..........
  数据包N:|-------------数据N(某数据包的部分数据)--------|            //某个数据包的最后一部分数据,而后面无其他数据包的数据黏在一起




D、一个接收的数据为一个包的部分数据,也即此包的数据长度大于1024个字节,也即如下:
     缓冲区:|--------------------------1024字节----------------------|
   数据包1:|-------------数据1(某数据包的部分数据)----------------|     //某个数据包的部分数据
   数据包2:|-------------数据2(某数据包的部分数据)----------------|     //某个数据包的部分数据
           ..........
  数据包N:|-------------数据N(某数据包的部分数据)另一个包的数据--|      //某个数据包的最后一部分数据,后面有其他数据包的数据黏在一起




      3、处理方式:
           第一次接收的时候,肯定可以接收到包括描述当前数据包长度的信息,通过解析还原此信息,就可以对比此次数据包的长度与缓冲区的长度,看是属于上述(第二点)的哪一种类型,根据不同的类型,进行相应的处理:


  A、类型A,这个情况处理最简单,根据数据包的长度信息,接收并解析数据即可


  B、类型B,这种情形得分两个情况处理,不过首先的先得获得缓冲区的数据,然后
     1)当N个数据包长度不超过1024字节时:
        通过递归,根据每一个包的长度来解析出每一个包的信息就好了


     2)当缓冲区的最后一部分数据还有某个包的部分数据时(暂称:数据包X的部分数据A1),那就又得分两种情况处理了:
        
       I、数据包X的部分数据A1的长度大于等于4字节的,也即包括了数据包X的长度信息,并保存这个部分数据A1,并获得数据包X的长度
           在下一次接收的时候,需要将刚才保存的数据与这次接收的数据进行粘合,然后在根据之前获得的长度进行处理


      II、数据包X的部分数据A1的长度小于4字节的,那就先保存这个部分数据A1
            在下一次接收的时候,需要将刚才保存的数据与这次接收的数据进行粘合,并解析出这个包的长度,然后根据这个长度去处理

            当然,这I,II两个类型,都可以安装II这个方式处理


           C、类型C,这个情况,需要进行记录两个信息,一个是这个数据包的长度,另外一个就是这个包的数据。
            1)先获得这个数据包的第一部分数据,保存,然后解析出这个包的长度
            2)继续接收数据,并粘合之前保存的数据,直到完成这个数据包所有的数据接收,然后解析这个数据包


           D、类型D,这个情况是类型C与类型B的混合体
           1)先根据类型C的方式进行数据保存,然后根据这个数据包的长度,来解析数据包
           2)然后根据类型B的情况,接收缓冲区最后一部分的数据、也即下一个数据包的部分数据,然后根据类型B的情况进行处理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值