高性能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. SSM定时任务(spring3.0)

    SSM定时任务主要分为两部分 1.applicationContext.xml配置文件设置 设置如下: 在xmlns中添加:xmlns:task="http://www.springfram ...

  2. JavaWeb之Cookie&Session

    Cookie 直译是:小饼干.实际上,Cookie就是由服务器给客户端,并且存储在客户端上的一份小数据 应用场景 自动登录,查看浏览记录,购物车 Cookie存在的意义 HTTP请求是无状态的,客户端 ...

  3. INSTALL_FAILED_TEST_ONLY

    查看博客:http://www.enjoytoday.cn/posts/159 Android studio安装apk无法安装,报错误,网上搜索可以看到都说是:* 调用者不被允许测试的测试程序*,但具 ...

  4. (转载)林轩田机器学习基石课程学习笔记1 — The Learning Problem

    (转载)林轩田机器学习基石课程学习笔记1 - The Learning Problem When Can Machine Learn? Why Can Machine Learn? How Can M ...

  5. 安装quickLook插件以及解决如何不能读取offic问题

    目录 @(安装quickLook插件) quickLook插件是Mac上的快速浏览的一个功能,现在win10系统上也能安装插件,这个插件可以快速浏览txt,doc,图片,表格等文件如下图: 我认为最方 ...

  6. Linux—服务器SSL/TLS快速检测工具(TLSSLed)

    一.下载TLSSLed [root@localhost ~]# yum install tlssled 二.服务器SSL/TLS快速检测工具TLSSLed 现在SSL和TLS被广泛应用服务器的数据加密 ...

  7. mean shift聚类算法的MATLAB程序

    mean shift聚类算法的MATLAB程序 凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 1. mean shift 简介 mean shift, 写的 ...

  8. 谈谈你对OOM的理解?

    (1)整体架构 (1)ByteBuffer使用native方法,直接在堆外分配内存. 当堆外内存(也即本地物理内存)不够时,就会抛出这个异常     ----GC Direct buffer memo ...

  9. 【BZOJ1443】[JSOI2009]游戏Game(二分图+博弈)

    BZOJ 题意: 给出一个\(n*m\)的网格,其中有一些障碍点. 现在两个人玩游戏,首先先手选定一个点,然后从后手开始轮流移动,不能移动者即输掉这次游戏. 规定不能移动到那些之前已经到过的格子上. ...

  10. Html学习之十(CSS选择器的使用--伪类选择器)

    伪类选择器 一.基于a标签. 1.:hover 选择鼠标滑过的超链接元素 2.:active 选择鼠标单击中的超链接元素 3.:link 选择未被访问的超链接元素 4.:visited 选择已经被访问 ...