【原创】c# socket 粘包 其实。。。
文章内容有错,请直接关闭~~~不要看了。丢人。
private static Dictionary<string, Packet> cache = new Dictionary<string, Packet>();
private static Dictionary<string, object> lockers = new Dictionary<string, object>();
public List<pkReturn> Package(ChannelReceiveEventArgs e)
{ byte[] data = new byte[e.Data.Count];
Buffer.BlockCopy(e.Data.Array, , data, , e.Data.Count);
int leng = e.Data.Count; if (!lockers.ContainsKey(e.Channel.ID)) lockers[e.Channel.ID] = new object(); //创建锁
lock (lockers[e.Channel.ID])
{
if (data != null)
{
string id = e.Channel.ID;
try
{
if (cache.ContainsKey(id))
{//如果客户端ID存在,就把接收到的字节,和之前的字节合起来
cache[id].BufferTemp = coder.UnionBytes(cache[id].BufferTemp, data);
}
else
{//如果客户端ID不存在集合内,就新建一个放入集合
Packet pk = new Packet();
cache[id] = pk;
cache[id].BufferTemp = new byte[leng];
Buffer.BlockCopy(data, , cache[id].BufferTemp, , data.Length);//拷贝数据
}
//循环处理包
List<pkReturn> lists = new List<pkReturn>();
cache[id].BufferCom = null;
do
{
pkReturn model = new pkReturn();
if (cache[id].BufferTemp.Length >= ) //1-4字节包大小 4-6两字节指令
{
byte[] sizetemp = new byte[];//大小
Buffer.BlockCopy(cache[id].BufferTemp, , sizetemp, , );
int size = (int)BitConverter.ToUInt32(sizetemp, );
size = size + ;
byte[] cmd = new byte[];//指令
Buffer.BlockCopy(cache[id].BufferTemp, , cmd, , );
if (size < && size > )
{
model.PkSize = size;
model.Cmd = (int)BitConverter.ToUInt32(cmd, );
}
else
{
e.Channel.Dispose();
Remove(id);//小于0 有问题 要清理掉客户端
lists.Clear();
break;
}
//解析包
byte[] tempbytes = new byte[size];
if (size < cache[id].BufferTemp.Length)
{ Buffer.BlockCopy(cache[id].BufferTemp, , tempbytes, , size);//拷贝一个完整包 byte[] temp = new byte[cache[id].BufferTemp.Length - size];//保存剩下的字节
Buffer.BlockCopy(cache[id].BufferTemp, size, temp, , cache[id].BufferTemp.Length - size);
cache[id].BufferTemp = temp; model.Bytes = coder.UnifyDecrypt(tempbytes);//对完整包解密
lists.Add(model);
}
else if (size == cache[id].BufferTemp.Length)
{
Buffer.BlockCopy(cache[id].BufferTemp, , tempbytes, , size);//根据获得大小拷贝字节
model.Bytes = coder.UnifyDecrypt(tempbytes);//对完整包解密
lists.Add(model);
cache[id].BufferTemp = null;//清空数据缓冲区
break;
}
else if (size > cache[id].BufferTemp.Length)
{//如果包头标记大小大于缓冲区大小,跳出
break;
}
else
{
Console.WriteLine("任何条件都不符合");
} }
else
{
break;
}
} while (true);
return lists;
}
catch (Exception ex)
{
Remove(id);
e.Channel.Dispose();
Console.WriteLine("分包解析函数异常:" + ex.Message + " 定位:" + ex.StackTrace);
throw new ArgumentException("分包解析函数异常 定位:"+ex.Message);
}
}
else
{
Console.WriteLine("data 为null");
throw new ArgumentException("分包解析函数异常 data 为null");
//return null;
}
}
}
【原创】c# socket 粘包 其实。。。的更多相关文章
- Socket粘包问题
这两天看csdn有一些关于socket粘包,socket缓冲区设置的问题,发现自己不是很清楚,所以查资料了解记录一下: 一两个简单概念长连接与短连接:1.长连接 Client方与Server方先建立通 ...
- C#下利用封包、拆包原理解决Socket粘包、半包问题(新手篇)
介于网络上充斥着大量的含糊其辞的Socket初级教程,扰乱着新手的学习方向,我来扼要的教一下新手应该怎么合理的处理Socket这个玩意儿. 一般来说,教你C#下Socket编程的老师,很少会教你如何解 ...
- [转]关于Socket粘包问题
这两天看csdn有一些关于socket粘包,socket缓冲区设置的问题,发现自己不是很清楚,所以查资料了解记录一下: 一两个简单概念长连接与短连接:1.长连接 Client方与Server方先建立通 ...
- 解决Socket粘包问题——C#代码
解决Socket粘包问题——C#代码 前天晚上,曾经的一个同事问我socket发送消息如果太频繁接收方就会有消息重叠,因为当时在外面,没有多加思考 第一反应还以为是多线程导致的数据不同步导致的,让他加 ...
- Python socket粘包解决
socket粘包: socket 交互send时,连续处理多个send时会出现粘包,soket会把两条send作为一条send强制发送,会粘在一起. send发送会根据recv定义的数值发送一个固定的 ...
- TCP Socket 粘包
这两天看csdn有一些关于socket粘包,socket缓冲区设置的问题.发现自己不是非常清楚,所以查资料了解记录一下: 一两个简单概念长连接与短连接: 1.长连接 Client方与Server ...
- socket粘包现象加解决办法
socket粘包现象分析与解决方案 简单远程执行命令程序开发(内容回顾) res = subprocess.Popen(cmd.decode('utf-8'),shell=True,stderr=su ...
- 百万年薪python之路 -- socket粘包问题解决
socket粘包问题解决 1. 高大上版解决粘包方式(自定制包头) 整体的流程解释 整个流程的大致解释: 我们可以把报头做成字典,字典里包含将要发送的真实数据的描述信息(大小啊之类的),然后json序 ...
- Socket粘包问题终极解决方案—Netty版(2W字)!
上一篇我们讲了<Socket粘包问题的3种解决方案>,但没想到评论区竟然炸了.介于大家的热情讨论,以及不同的反馈意见,本文就来做一个扩展和延伸,试图找到问题的最优解,以及消息通讯的最优解决 ...
- socket 粘包问题(转)
https://www.v2ex.com/t/234785#reply3 1. 面向字节流的 IO 都有这个问题. socket 中 tcp 协议是面向流的协议,发送方发送和接收方的接收并不是一一对应 ...
随机推荐
- hibernate框架学习第五天:数据查询、投影等
复习day1环境搭建CRUD操作DB6个核心的APIday2TO PO DO 及其状态切换OID 自然主键 代理主键(uuid)一级缓存 Session绑定 load/get关系1对1 1对多(重点) ...
- $Django 多表操作(增删改查,基于双下划线,对象的查询) 在Python脚本中调用Django环境
在Python脚本中调用Django环境. import osif __name__ == '__main__': os.environ.setdefault("DJANGO_SETTING ...
- jmeter设置全局变量
2017年4月20日 10:07:37 星期四 情景, 从第一个请求的结果中匹配出code, 当作参数去做下次请求 以抢红包为例: 1. 创建红包, 并从返回结果中获取红包code 2. 将code设 ...
- mybatis:递归查询,关联查询传入多个参数
需求是:递归查询资源 1.资源类 EntityBaseResource: public final class EntityBaseResource { private Long resID = 0l ...
- List集合三种遍历方法
List<String> list = new ArrayList<String>();list.add("aaa");list.add("bbb ...
- 41)django-admin
一:介绍 通过django admin可以快速生成后台管理功能. 二:设置 工程同名下settings.py 1)在INSTALLED_APPS中增加django.contrib.admin 2)在I ...
- The servlet name already exists.解决方法
The servlet name already exists.解决方法 当我们建立过同名的servlet文件,然后又将其删掉后再用同类名字建一个servlet时就会报错.解决办法:web.xml里面 ...
- nginx实战(三)之静态资源web服务(跨站访问)
语法 虽然说浏览器禁止跨站访问以防(CSRF),但出于一些原因还是要进行跨站访问,服务端通过设置头信息Access-Control-Allow-Orign:xxxx,客户端收到后就会允许跨站访问了 实 ...
- selenium+python-autoit文件上传
前言 关于非input文件上传,点上传按钮后,这个弹出的windows的控件了,已经跳出三界之外了,不属于selenium的管辖范围(selenium不是万能的,只能操作web上元素).autoit工 ...
- C/C++中二进制与文本方式打开文件的区别
二进制与文本文件主要有两个大的区别: 1.换行符的区别: Windows平台下 对于Windows文本文件,它们使用回车和换行来表示换行符:如果以“文本”方式打开文件,当读取文件的时候,系统会将所有 ...