高性能TcpServer(C#) - 1.网络通信协议

高性能TcpServer(C#) - 2.创建高性能Socket服务器SocketAsyncEventArgs的实现(IOCP)

高性能TcpServer(C#) - 3.命令通道(处理:掉包,粘包,垃圾包)

高性能TcpServer(C#) - 4.文件通道(处理:文件分包,支持断点续传)

高性能TcpServer(C#) - 5.客户端管理

高性能TcpServer(C#) - 6.代码下载

处理原理

每个client创建各自的byte[]数组,通过遍历每个字节的数据

1.判断包长,确定掉包;

2.判断解析完后byte数组是否还有未解析的数据,确定粘包;

3.判断包头,确定垃圾包;

缓存数据类

/// <summary>

/// 缓存数据类

/// </summary>

public class CByteBuffer

{

// 默认1k

int m_iBufferSize = 1024 * 1;

// 数据解析

byte[] m_abyBuf;

int m_iPosition = 0;

int m_iRecvLength = 0;

bool bWaitRecvRemain;// 数据未接收完等待接收

object m_lock = new object(); // 内部同步锁

public int Position

{

get { return m_iPosition; }

set { m_iPosition = value; }

}

public int RecvLength

{

get { return m_iRecvLength; }

set { m_iRecvLength = value; }

}

public bool WaitRecvRemain

{

get { return bWaitRecvRemain; }

set { bWaitRecvRemain = value; }

}

public CByteBuffer(int buffSize)

{

m_iBufferSize = buffSize;

m_abyBuf = new byte[m_iBufferSize];

}

public int GetPosition()

{

return m_iPosition;

}

public int GetRecvLength()

{

return m_iRecvLength;

}

public void Put(SocketAsyncEventArgs e)

{

int iLength = e.BytesTransferred;

if (m_iRecvLength + iLength >= m_iBufferSize)

{

Clear();

return;

}

lock (m_lock)

{

Array.Copy(e.Buffer, e.Offset, m_abyBuf, m_iRecvLength, iLength);

m_iRecvLength += iLength;

}

}

public byte GetByte()

{

bWaitRecvRemain = false;

if (m_iPosition >= m_iRecvLength)

{

bWaitRecvRemain = true;

return 0;

}

byte byRet;

lock (m_lock)

{

byRet = m_abyBuf[m_iPosition];

}

m_iPosition++;

return byRet;

}

public byte[] GetByteArray(int Length)

{

bWaitRecvRemain = false;

if (m_iPosition + Length > m_iRecvLength)

{

bWaitRecvRemain = true;

return null;

}

byte[] ret = new byte[Length];

lock (m_lock)

{

Array.Copy(m_abyBuf, m_iPosition, ret, 0, Length);

m_iPosition += Length;

}

return ret;

}

public bool HasRemaining()

{

return m_iPosition < m_iRecvLength;

}

public int Remaining()

{

return m_iRecvLength - m_iPosition;

}

public void Clear()

{

m_iPosition = 0;

m_iRecvLength = 0;

bWaitRecvRemain = false;

}

~CByteBuffer()

{

m_abyBuf = null;

Dispose(false);

}

protected virtual void Dispose(bool disposing)

{

if (disposing)

{

GC.SuppressFinalize(this);

}

}

public void Dispose()

{

Dispose(true);

}

}

协议解析类

public void Process(CByteBuffer bBuffer, CProtocolAnalysis analysis, string sn)

{

analysis.BagStatus = CProtocolAnalysis.EBagStatus.BagNone;

analysis.WhetherToSend = false;

int iPosition = bBuffer.Position;

byte head1 = 0; byte head2 = 0; byte head3 = 0; byte head4 = 0; byte head5 = 0; byte head6 = 0; bool headok = false;

if (!bBuffer.HasRemaining()) return;

while (bBuffer.HasRemaining())

{

head1 = bBuffer.GetByte(); if (!analysis.IsRemainData(iPosition, bBuffer, analysis)) return;

if (HEAD1 == head1)

{

iPosition = bBuffer.Position - 1;

head2 = bBuffer.GetByte(); if (!analysis.IsRemainData(iPosition, bBuffer, analysis)) return;

head3 = bBuffer.GetByte(); if (!analysis.IsRemainData(iPosition, bBuffer, analysis)) return;

head4 = bBuffer.GetByte(); if (!analysis.IsRemainData(iPosition, bBuffer, analysis)) return;

head5 = bBuffer.GetByte(); if (!analysis.IsRemainData(iPosition, bBuffer, analysis)) return;

head6 = bBuffer.GetByte(); if (!analysis.IsRemainData(iPosition, bBuffer, analysis)) return;

if (HEAD2 == head2 && HEAD3 == head3 && HEAD4 == head4 && HEAD5 == head5 && HEAD6 == head6)

{

headok = true;

break;

}

else

{

CLogHelp.AppendLog("Error,Unable to parse the data2:Position=" + iPosition.ToString() + ",Index=" + (bBuffer.GetPosition()).ToString() + ",Head2=" + head2.ToString());

}

}

else

{

CLogHelp.AppendLog("Error,Unable to parse the data1:Position=" + iPosition.ToString() + ",Index=" + (bBuffer.GetPosition()).ToString() + ",Head1=" + head1.ToString());

}

}

if (!bBuffer.HasRemaining())

{

if (headok)

{

if (!analysis.IsRemainData(iPosition, bBuffer, analysis)) return;

}

return;

}

byte[] arrlen = bBuffer.GetByteArray(4); if (!analysis.IsRemainData(iPosition, bBuffer, analysis)) return;

int len = CCommonFunc.String2Int(CCommonFunc.ByteToString(arrlen)); if (-1 == len) return;

byte[] source = bBuffer.GetByteArray(len); if (!analysis.IsRemainData(iPosition, bBuffer, analysis)) return;

if (!bBuffer.HasRemaining())

{

bBuffer.Clear();

}

else

{

analysis.BagStatus = CProtocolAnalysis.EBagStatus.BagStick;

}

// #WaterMeter-001#01##

string data = CCommonFunc.ByteToString(source);

if (null == data || 0 == data.Length || data.Length - 1 != data.LastIndexOf(SPLIT1))

{

return;

}

data = data.Substring(1, data.Length - 2);

string[] item = data.Split(SPLIT1);

if (null == item || 4 != item.Length)

{

return;

}

string uid = item[0];

string taskid = item[1];

int cmd = CCommonFunc.String2Int(item[2]);

string content = item[3];

Program.AddMessage("R: [" + sn + "] cmd=" + cmd.ToString() + " data=" + data);

analysis.Cmd = cmd;

analysis.Uid = uid;

analysis.TaskId = taskid;

if (cmd == 1 || cmd == 2 || cmd == 3 || cmd == 4 || cmd == 5 || cmd == 6 || cmd == 7)

{

analysis.WhetherToSend = true;

}

string softtype = "";

try

{

switch (cmd)

{

case 1:

analysis.Msg = "ok";

break;

case 2:

analysis.Msg = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

break;

case 3:

// HTEMP=0263#WaterMeter-001#1520557004#03#buildid=44@edmid=37@meterid=1228@senddate=2018-02-05 17:36:22@[{132,0.0000}+{132,0.0000}+{132,0.0000}+{132,0.0000}+{132,0.0000}+{132,0.0000}+{132,0.0000}+{132,0.0000}+{132,0.0000}+{132,0.0000}+{132,0.0000}+{132,0.0000}+{132,0.0000}]#

analysis.Msg = "ok";

break;

case 4:

{

// 获取版本信息

softtype = content.Split(SPLIT2)[1];

StorageFile(softtype, System.Windows.Forms.Application.StartupPath + "\\test.zip");

analysis.Msg = "2";// version

}

break;

case 5:

// 获取包数

{

softtype = content.Split(SPLIT2)[1];

if (!dicSoft.ContainsKey(softtype))

{

StorageFile(softtype, System.Windows.Forms.Application.StartupPath + "\\test.zip");

}

// 获取包数

int count = 0;

FileCut entity = null;

dicSoft.TryGetValue(softtype, out entity);

if (null != entity) count = entity.Count;

analysis.Msg = count.ToString();

}

break;

case 6:

// 执行更新动作

{

string[] items = content.Split(SPLIT2);

softtype = items[1];

int downindex = CCommonFunc.String2Int(items[2]);

if (!dicSoft.ContainsKey(softtype))

{

analysis.Msg = "error@" + softtype + " 未找到更新文件,请先获取包数";

}

else

{

FileCut entity = null;

dicSoft.TryGetValue(softtype, out entity);

if (null != entity)

{

string filedata = "";

entity.Data.TryGetValue(downindex, out filedata);

if (string.IsNullOrEmpty(filedata))

analysis.Msg = "error@" + softtype + " 第" + downindex + "包的数据为空";

else

analysis.Msg = filedata;

}

}

}

break;

case 7:

// 更新版本信息(update sql)

analysis.Msg = "ok";

break;

}

}

catch (Exception ex)

{

analysis.Msg = "error@" + ex.Message;

}

Program.AddMessage("S: [" + sn + "] cmd=" + cmd.ToString() + " data=" + analysis.Msg);

}

测试效果

正常包

HTEMP=0026#Meter-001#1533022506#01##

掉包(分两包发送)

HTEMP=0026#

Meter-001#1533022506#01##

粘包(两包一起发送)

HTEMP=0026#Meter-001#1533022506#01##HTEMP=0026#Meter-001#1533022506#01##

高性能TcpServer(C#) - 3.命令通道(处理:掉包,粘包,垃圾包)的更多相关文章

  1. 高性能TcpServer(C#) - 4.文件通道(处理:文件分包,支持断点续传)

    高性能TcpServer(C#) - 1.网络通信协议 高性能TcpServer(C#) - 2.创建高性能Socket服务器SocketAsyncEventArgs的实现(IOCP) 高性能TcpS ...

  2. C#高性能大容量SOCKET并发(五):粘包、分包、解包

    原文:C#高性能大容量SOCKET并发(五):粘包.分包.解包 粘包 使用TCP长连接就会引入粘包的问题,粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一 ...

  3. DELPHI高性能大容量SOCKET并发(四):粘包、分包、解包

    粘包 使用TCP长连接就会引入粘包的问题,粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾.粘包可能由发送方造成,也可能由接收方造成.TCP为提 ...

  4. 高性能TcpServer(C#) - 1.网络通信协议

    高性能TcpServer(C#) - 1.网络通信协议 高性能TcpServer(C#) - 2.创建高性能Socket服务器SocketAsyncEventArgs的实现(IOCP) 高性能TcpS ...

  5. 高性能TcpServer(C#) - 2.创建高性能Socket服务器SocketAsyncEventArgs的实现(IOCP)

    高性能TcpServer(C#) - 1.网络通信协议 高性能TcpServer(C#) - 2.创建高性能Socket服务器SocketAsyncEventArgs的实现(IOCP) 高性能TcpS ...

  6. 高性能TcpServer(C#) - 5.客户端管理

    高性能TcpServer(C#) - 1.网络通信协议 高性能TcpServer(C#) - 2.创建高性能Socket服务器SocketAsyncEventArgs的实现(IOCP) 高性能TcpS ...

  7. 高性能TcpServer(C#) - 6.代码下载

    高性能TcpServer(C#) - 1.网络通信协议 高性能TcpServer(C#) - 2.创建高性能Socket服务器SocketAsyncEventArgs的实现(IOCP) 高性能TcpS ...

  8. 高性能TcpServer(Java) - Netty

    源码下载 -> 提取码  QQ:505645074 Netty 是一个高性能.异步事件驱动的 NIO 框架,它提供了对 TCP.UDP 和文件传输的支持,作为一个异步 NIO 框架,Netty ...

  9. 网络编程之模拟ssh远程执行命令、粘包问题 、解决粘包问题

    目录 模拟ssh远程执行命令 服务端 客户端 粘包问题 什么是粘包 TCP发送数据的四种情况 粘包的两种情况 解决粘包问题 struct模块 解决粘包问题 服务端 客户端 模拟ssh远程执行命令 服务 ...

随机推荐

  1. go开发注意事项和dos的一些操作

    不需要加分号 写法 go编译器一行一行编译,所以多条语句不能写在同一行,否则会报错 go语言定义的变量或者import的包如果没有使用到,代码不能通过编译 func main() { ... } 只能 ...

  2. Java的23种设计模式,详细讲解(三)

    本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...

  3. Python中使用requests和parsel爬取喜马拉雅电台音频

    场景 喜马拉雅电台: https://www.ximalaya.com/ 找到一步小说音频,这里以下面为例 https://www.ximalaya.com/youshengshu/16411402/ ...

  4. 反射实体类拼接SQL语句

    实体类基类: using System; using System.Collections.Generic; using System.Linq; using System.Reflection; u ...

  5. .net core 使用ViewComponent

    .net core 中的局部视图组件是ViewComponent,可以用于建制重复使用公共功能组件 一.新建一个类DemoViewComponent(必须以ViewComponent结尾)且继承Vie ...

  6. CODING 告诉你硅谷项目经理的项目管理之道

    写在前面 优秀的项目管理者是怎么工作的,如何把一个研发团队的绩效激发到最大? 我们精心挑选了几篇硅谷科技公司研发管理者的 README 进行翻译. README 主要用来向团队成员展示项目管理者的工作 ...

  7. 渗透测试之wep无线网络破解

    WEP 无线网络破解 WEP(无线等效协议)于 1999 年诞生,并且是用于无线网络的最古老的安全标准.在 2003 年,WEP 被 WPA 以及之后被 WPA2 取代.由于可以使用更加安全的协议,W ...

  8. Python—网络抓包与解包(pcap、dpkt)

    pcap安装 [root@localhost ~]# pip install pypcap 抓包与解包 # -*- coding:utf-8 -*- import pcap, dpkt import ...

  9. drf框架知识总结

  10. 《Zabbix》

    https://github.com/itnihao/zabbix-rpm https://github.com/itnihao/zabbix-book 一.zabbix支持的主要监控方式: zabb ...