码迷,mamicode.com
首页 > Windows程序 > 详细

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

时间:2015-05-12 11:28:10      阅读:500      评论:0      收藏:0      [点我收藏+]

标签:c#   socket   粘包   断包   

    一直是用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的情况进行处理

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

标签:c#   socket   粘包   断包   

原文地址:http://blog.csdn.net/11097082/article/details/45665087

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!