From 0b6046ee6819dadc97ef1c890c577607b00be0d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=99=BA=E8=83=BD=E5=A4=A7=E7=9F=B3=E5=A4=B4?= Date: Thu, 4 Jan 2024 08:34:31 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BC=95=E5=85=A5TPKT=E7=BC=96=E7=A0=81?= =?UTF-8?q?=E5=99=A8TPKTCodec=EF=BC=8C=E8=A7=A3=E5=86=B3=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E7=AB=AF=E7=B2=98=E5=8C=85=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NewLife.Siemens/Protocols/S7PLC.cs | 6 +-- NewLife.Siemens/Protocols/S7Server.cs | 2 + NewLife.Siemens/Protocols/TPKT.cs | 26 ++++++----- NewLife.Siemens/Protocols/TPKTCodec.cs | 64 ++++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 15 deletions(-) create mode 100644 NewLife.Siemens/Protocols/TPKTCodec.cs diff --git a/NewLife.Siemens/Protocols/S7PLC.cs b/NewLife.Siemens/Protocols/S7PLC.cs index be0b39f..4850c67 100644 --- a/NewLife.Siemens/Protocols/S7PLC.cs +++ b/NewLife.Siemens/Protocols/S7PLC.cs @@ -254,11 +254,11 @@ private async Task RequestAsync(Stream stream, COTP request, CancellationT try { var pk = request.GetBytes(true); - var buf = pk.ReadBytes(); + //var buf = pk.ReadBytes(); using var closeOnCancellation = cancellationToken.Register(Close); - //await pk.CopyToAsync(stream, cancellationToken); - await stream.WriteAsync(buf, 0, buf.Length, cancellationToken); + await pk.CopyToAsync(stream, cancellationToken); + //await stream.WriteAsync(buf, 0, buf.Length, cancellationToken); return await COTP.ReadAsync(stream, cancellationToken).ConfigureAwait(false); } catch (Exception exc) diff --git a/NewLife.Siemens/Protocols/S7Server.cs b/NewLife.Siemens/Protocols/S7Server.cs index 6bfdc51..9df0052 100644 --- a/NewLife.Siemens/Protocols/S7Server.cs +++ b/NewLife.Siemens/Protocols/S7Server.cs @@ -10,6 +10,8 @@ public S7Server() { Port = 102; ProtocolType = NetType.Tcp; + + Add(new TPKTCodec()); } } diff --git a/NewLife.Siemens/Protocols/TPKT.cs b/NewLife.Siemens/Protocols/TPKT.cs index 6c114b0..d0783f7 100644 --- a/NewLife.Siemens/Protocols/TPKT.cs +++ b/NewLife.Siemens/Protocols/TPKT.cs @@ -12,6 +12,7 @@ namespace NewLife.Siemens.Protocols; /// public class TPKT { + #region 属性 /// 版本 public Byte Version { get; set; } @@ -23,21 +24,11 @@ public class TPKT /// 数据 public Packet Data { get; set; } - - /// 实例化 - public TPKT() { } - - private TPKT(Byte version, Byte reserved1, Int32 length, Byte[] data) - { - Version = version; - Reserved = reserved1; - Length = (UInt16)length; - Data = data; - } + #endregion /// 解析数据 /// - public void Read(Packet pk) + public TPKT Read(Packet pk) { var buf = pk.ReadBytes(0, 4); Version = buf[0]; @@ -45,6 +36,8 @@ public void Read(Packet pk) Length = buf.ToUInt16(2, false); if (pk.Total > 4) Data = pk.Slice(4, Length); + + return this; } /// 解析数据 @@ -87,6 +80,15 @@ public Byte[] ToArray() return ms.ToArray(); } + /// 获取字节数组 + /// + public Packet ToPacket() + { + var ms = new MemoryStream(); + Write(ms); + return new Packet(ms); + } + /// /// Reads a TPKT from the socket Async /// diff --git a/NewLife.Siemens/Protocols/TPKTCodec.cs b/NewLife.Siemens/Protocols/TPKTCodec.cs new file mode 100644 index 0000000..f31fe57 --- /dev/null +++ b/NewLife.Siemens/Protocols/TPKTCodec.cs @@ -0,0 +1,64 @@ +using NewLife.Data; +using NewLife.Messaging; +using NewLife.Model; +using NewLife.Net.Handlers; + +namespace NewLife.Siemens.Protocols; + +/// 编码器 +public class TPKTCodec : MessageCodec +{ + /// 实例化编码器 + public TPKTCodec() => UserPacket = false; + + /// 编码 + /// + /// + /// + protected override Object Encode(IHandlerContext context, TPKT msg) + { + if (msg is TPKT cmd) return cmd.ToPacket(); + + return null; + } + + /// 解码 + /// + /// + /// + protected override IList Decode(IHandlerContext context, Packet pk) + { + var ss = context.Owner as IExtend; + if (ss["Codec"] is not PacketCodec pc) + ss["Codec"] = pc = new PacketCodec { GetLength = p => GetLength(p, 3, 1) - 4, Offset = 3 }; + + var pks = pc.Parse(pk); + var list = pks.Select(e => new TPKT().Read(e)).ToList(); + + return list; + } + + /// 连接关闭时,清空粘包编码器 + /// + /// + /// + public override Boolean Close(IHandlerContext context, String reason) + { + if (context.Owner is IExtend ss) ss["Codec"] = null; + + return base.Close(context, reason); + } + + /// 是否匹配响应 + /// + /// + /// + protected override Boolean IsMatch(Object request, Object response) + { + if (request is not TPKT req || response is not TPKT res) return false; + + // 不支持链路复用,任意响应都是匹配的 + + return true; + } +} \ No newline at end of file