public void TestWriteRead() { PackageHead target = new PackageHead(); PackageHead other = new PackageHead(); byte[] temp = new byte[PackageHead.SizeOf]; target.Flags = byte.MinValue; target.MessageLength = ushort.MinValue; target.WriteTo(temp, 0); other.ReadFrom(temp, 0); Assert.AreEqual(target, other); target.Flags = (PackageHeadFlags)byte.MaxValue; target.MessageLength = ushort.MaxValue; target.WriteTo(temp, 0); other.ReadFrom(temp, 0); Assert.AreEqual(target, other); Random random = new Random(); int index = random.Next(100); temp = new byte[PackageHead.SizeOf + 100]; target.Flags = (PackageHeadFlags)12; target.MessageLength = 16; target.WriteTo(temp, index); other.ReadFrom(temp, index); Assert.AreEqual(target, other); }
/// <summary> /// 反序列化接收到的数据,输出message /// messageHandler需要保证线程安全 /// </summary> public TcpSession.ReceivedHandler CreateReceivedHandler(TcpSession session, Action<TcpSession, object> messageHandler) { bool isInitialized = false; bool isReadingHeader = true; bool isPartial = false; var partialStream = new MemoryStream(); TcpSession.ReceivedHandler handler = stream => { if (!isInitialized) { Debug.Assert(stream.Length == 0 && stream.Position == 0); isInitialized = true; return PackageHead.SizeOf; } if (isReadingHeader) { PackageHead header = new PackageHead(); header.ReadFrom(stream.GetBuffer(), (int)stream.Position); isReadingHeader = false; isPartial = ((header.Flags & PackageHeadFlags.Partial) == PackageHeadFlags.Partial); return header.MessageLength; } else { if (isPartial) // 超大包未接收完全 { // 在临时缓冲中拼包 stream.WriteTo(partialStream); } else if (partialStream.Length != 0) // 超大包最后一个分包 { // 拼包然后反序列化 stream.WriteTo(partialStream); object message = null; try { message = this.serializer.Deserialize(partialStream.GetBuffer(), 0, (int)partialStream.Length); } catch (Exception e) { OnMessageDeserializeFailed(e); } if (message != null) messageHandler(session, message); partialStream.Position = 0; partialStream.SetLength(0); } else // 普通大小的包 { // 直接反序列化 object message = null; try { message = this.serializer.Deserialize(stream.GetBuffer(), (int)stream.Position, (int)stream.Length); } catch (Exception e) { OnMessageDeserializeFailed(e); } if (message != null) messageHandler(session, message); } isReadingHeader = true; return PackageHead.SizeOf; } }; return handler; }
/// <summary> /// 序列化要发送的message /// </summary> public TcpSession.SendingHandler CreateSendingHandler() { TcpSession.SendingHandler handler = (messages, stream) => { foreach (var message in messages) { // 保留包头空间 var headerPosition = stream.Position; stream.SetLength(stream.Length + PackageHead.SizeOf); stream.Position += PackageHead.SizeOf; // 序列化消息 serializer.Serialize(message, stream); PackageHead header = new PackageHead(); var length = stream.Length - (headerPosition + PackageHead.SizeOf); // 超大包 if (length > ushort.MaxValue) { // 写入第一个包的包头 header.Flags |= PackageHeadFlags.Partial; header.MessageLength = ushort.MaxValue; header.WriteTo(stream.GetBuffer(), (int)headerPosition); length -= ushort.MaxValue; // 从第一个包末尾截断,把剩余数据拷到临时缓冲中 var keptSize = headerPosition + ushort.MaxValue + PackageHead.SizeOf; var dataLeft = new byte[stream.Length - keptSize]; var offset = 0; stream.Position = keptSize; stream.Read(dataLeft, 0, dataLeft.Length); stream.Position = keptSize; stream.SetLength(keptSize); // 从临时缓冲中把剩余数据加上包头写入 while (length > 0) { ushort truncateLength = ushort.MaxValue; // 最后的部分 if (length <= ushort.MaxValue) { truncateLength = (ushort)length; header.Flags &= ~PackageHeadFlags.Partial; } header.MessageLength = truncateLength; header.WriteTo(stream); stream.Write(dataLeft, offset, truncateLength); offset += truncateLength; length -= truncateLength; } Debug.Assert(offset == dataLeft.Length); } else // 普通大小的包 { // 写入包头 header.MessageLength = (ushort)length; header.WriteTo(stream.GetBuffer(), (int)headerPosition); } } }; return handler; }