TCP通信解包
虽说这是一个老生长谈的问题,不过网上基本很少见完整业务;或多或少都没有写完或者存在bug。接收到的数据包可以简单分成:小包、大包、跨包三种情况,根据这三种情况作相对应的拆包处理,示例如下:

1 /***************************************************************************************************** 2 * 本代码版权归@wenli所有,All Rights Reserved (C) 2015-2016 3 ***************************************************************************************************** 4 * CLR版本:4.0.30319.42000 5 * 唯一标识:7a846c42-665d-4628-b91f-9d58b670437d 6 * 机器名称:WENLI-PC 7 * 联系人邮箱:wenguoli_520@qq.com 8 ***************************************************************************************************** 9 * 项目名称:$projectname$ 10 * 命名空间:APM.Core 11 * 类名称:UserToken 12 * 创建时间:2016/11/30 16:56:29 13 * 创建人:wenli 14 * 创建说明: 15 *****************************************************************************************************/ 16 using System; 17 using System.Net.Sockets; 18 19 namespace APM.Core 20 { 21 /// <summary> 22 /// tcp用户信息 23 /// </summary> 24 public class UserToken 25 { 26 private int offset, count = 0; 27 28 private byte[] _myBuffer; 29 30 private byte[] _myLenBuffer; 31 32 public int MaxBufferSize 33 { 34 get; private set; 35 } 36 37 /// <summary> 38 /// 用户标识 39 /// </summary> 40 public string ID 41 { 42 get; set; 43 } 44 /// <summary> 45 /// 连接的客户 46 /// </summary> 47 public Socket Client 48 { 49 get; set; 50 } 51 52 /// <summary> 53 /// 会话验证码 54 /// </summary> 55 public int Auth 56 { 57 get; set; 58 } 59 60 61 62 public UserToken(int maxBufferSize = 10 * 1024) 63 { 64 this.MaxBufferSize = maxBufferSize; 65 this.ReceiveBuffer = new byte[this.MaxBufferSize]; 66 } 67 68 69 70 /// <summary> 71 /// 处理收取数据 72 /// 解包 73 /// </summary> 74 /// <param name="receiveData"></param> 75 /// <param name="action"></param> 76 internal void UnPackage(byte[] receiveData, Action<TcpPackage> action) 77 { 78 //当前包取内容的 79 if (offset == 0) 80 { 81 var packageLength = 0; 82 if (this._myLenBuffer != null) //长度不完整的(包头不完整的) 83 { 84 //调整receiveData包内容 85 var nData = new byte[this._myLenBuffer.Length + receiveData.Length]; 86 Buffer.BlockCopy(this._myLenBuffer, 0, nData, 0, this._myLenBuffer.Length); 87 Buffer.BlockCopy(receiveData, 0, nData, this._myLenBuffer.Length, receiveData.Length); 88 receiveData = nData; 89 nData = null; 90 this._myLenBuffer = null; 91 } 92 else //全新包(包头完整的) 93 { 94 packageLength = TcpPackage.GetLength(receiveData); 95 if (packageLength == 0) 96 return; 97 } 98 if (packageLength < receiveData.Length) 99 {100 var package = TcpPackage.Parse(receiveData);101 if (action != null && package != null)102 {103 action(package);104 }105 106 var slen = TcpPackage.GetLength(receiveData, package.Length);107 if (slen >= 9)108 {109 var next = new byte[receiveData.Length - package.Length];110 Buffer.BlockCopy(receiveData, package.Length, next, 0, next.Length);111 this.UnPackage(next, action);112 }113 }114 else if (packageLength == receiveData.Length)115 {116 var package = TcpPackage.Parse(receiveData);117 if (action != null && package != null)118 {119 action(package);120 }121 }122 else if (packageLength > receiveData.Length)123 {124 this.count = packageLength;125 this._myBuffer = new byte[packageLength];126 Buffer.BlockCopy(receiveData, 0, this._myBuffer, 0, receiveData.Length);127 this.offset = receiveData.Length;128 }129 receiveData = null;130 131 }132 else //跨包取内容的133 {134 if (receiveData.Length + offset < count) //包内容超出135 {136 Buffer.BlockCopy(receiveData, 0, this._myBuffer, offset, receiveData.Length);137 offset += receiveData.Length;138 }139 else if (receiveData.Length + offset >= count) //包内容短的140 {141 var packageLast = count - offset;142 Buffer.BlockCopy(receiveData, 0, this._myBuffer, offset, packageLast);143 var package = TcpPackage.Parse(this._myBuffer);144 if (action != null && package != null)145 {146 action(package);147 }148 this._myBuffer = null;149 count = offset = 0;150 var receiveLast = receiveData.Length - packageLast;151 if (receiveLast >= 4)//包含包头长度152 {153 var packageLength = TcpPackage.GetLength(receiveData, packageLast);154 if (packageLength > 0)155 {156 if (receiveLast > packageLength)157 {158 var nextData = new byte[receiveLast];159 Buffer.BlockCopy(receiveData, packageLast, nextData, 0, receiveLast);160 this.UnPackage(nextData, action);161 }162 else163 {164 this._myBuffer = new byte[packageLength];165 Buffer.BlockCopy(receiveData, packageLast, this._myBuffer, 0, receiveLast);166 offset = receiveLast;167 count = packageLength;168 }169 }170 else171 {172 this._myBuffer = null;173 count = offset = 0;174 this._myLenBuffer = null;175 }176 }177 else if (receiveLast > 0)//不包含包头长度178 {179 this._myLenBuffer = new byte[receiveLast];180 Buffer.BlockCopy(receiveData, packageLast, this._myLenBuffer, 0, receiveLast);181 if (TcpPackage.GetLength(this._myLenBuffer) == 0)182 {183 this._myLenBuffer = null;184 }185 this._myBuffer = null;186 count = offset = 0;187 }188 }189 receiveData = null;190 }191 }192 193 public byte[] ReceiveBuffer194 {195 get; set;196 }197 198 public void ClearReceiveBuffer()199 {200 for (int i = 0; i < this.ReceiveBuffer.Length; i++)201 {202 this.ReceiveBuffer[i] = 0;203 }204 }205 }206 }
有了解包就可以发超长消息、文件等
异步tcp通信——APM.Core 服务端概述
异步tcp通信——APM.Core 解包
异步tcp通信——APM.Server 消息推送服务的实现
异步tcp通信——APM.ConsoleDemo
转载请标明本文来源:http://www.cnblogs.com/yswenli/
更多内容欢迎star作者的github:https://github.com/yswenli/APM
如果发现本文有什么问题和任何建议,也随时欢迎交流~
继续阅读与本文标签相同的文章
上一篇 :
异步tcp通信——APM.Core 服务端概述
-
DOTNET Core 命令
2026-06-02栏目: 教程
-
always on 集群
2026-06-02栏目: 教程
-
快速在Ubuntu安装PHP网站
2026-06-02栏目: 教程
-
.NET平台常用的框架整理
2026-06-02栏目: 教程
-
寻找源代码
2026-06-02栏目: 教程

