MemoryStream MemoryStream; //此类内存字节流
int HEAD_LENGTH = 8; //包体长度字段+协议的唯一标识。其中前4个字节用来标识包体长度,后四个字节用来标识协议ID。
byte[] buffer = new byte[1024*10]; //开辟10k大小的缓冲区,用于接收数据
TcpClient client = null;
byte[] lockObj = new byte[1];
BinaryReader reader;
// 初始化
void Init()
{
client = new TcpClient();
memoryStream = new MemoryStream()
reader = new BinaryReader(memoryStream);
client.BeginConnect(127.0.0.1, 8888, new AsyncCallback(OnConnected), null);
}
// 连接建立的回调函数
void OnConnected(IAsyncResult result)
{
if(client.Connected)
{
client.GetStream().BeginRead(buffer, 0 , 1024*10, new AsyncCallback(OnReadData),null);
}
else
{
Debug.LogError("网络异常");
}
}
// 当读到数据
void OnReadData(IAsyncResult result)
{
int dataLength = 0;
try
{
lock(lockObj)
{
dataLength = client.GetStream().EndRead(result);
}
// <span style="font-family: Arial, Helvetica, sans-serif;">组包处理</span>
GeneratePacket(buffer, dataLength);
// 继续读取
lock(lockObj)
{
// 首先要清空缓冲区
Array.Clear(buffer, 0, 1024*10);
// 然后读取
client.GetStream().BeginRead(buffer, 0, 1024*10, new AsyncCallback(OnReadData), null);
}
}
catch(Exception e)
{
Debug.LogError("网络异常");
}
}
// 组包处理
void GeneratePacket(byte[] bytes, int length)
{
memoryStream.Seek(0, SeekOrigin.End); // 文件末尾偏移0,即继续续写
memoryStream.Write(bytes, 0, length); // 写入length长度的数据
memoryStream.Seek(0, SeekOrigin.Begin); // 指针重置为0
// 数据包的长度
int dataLength = memoryStream.Length - memoryStream.Position; //当前数据包的长度-指针的起始位置
while(dataLength >= HEAD_LENGTH)
{
UInt32 messageDataLen = reader.ReadUInt32(); //这一步做完之后,memoryStream的Position,已经由原来位置,递增了4,因为reader读取4个字节
UInt32 protocolID = 0;
dataLength = memoryStream.Length - memoryStream.Position
if (dataLength >=messageDataLen+ 4) // 这里messageLen是数据部分,而+4,这个4protocolID占的四个字节
{
protocolID = reader.ReadUInt32();
MemoryStream tmpStream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(tmpStream);
writer.Write(reader.ReadBytes(messageLen));
tmpStream.Seek(0, SeekOrigin.Begin);
HandleMessage(protocolID, tmpStream);
}
else //如果数据不够,那么因为上面第一次reader.ReadUInt32()的时候,Position,已经由原来位置,递增了4,所以要减去4
{
memoryStream.Position = memoryStream.Position - 4;
break;
}
}
dataLength = memoryStream.Length - memoryStream.Position;
byte[] remainBytes = reader.ReadBytes(dataLength);
memoryStream.SetLength(0);
memoryStream.Write(remainBytes, 0, remainBytes.Length); //将剩余的数据包向前搬移。
}
// 处理消息
void HandleMessage(Uint32 protocolID, MemoryStream paramData)
{
/// do sth...
}
TCP组包
最新推荐文章于 2024-06-30 23:40:48 发布