From d6356dd8706fe6462f7dfb0ae7db9c9ec7102001 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: Tue, 3 Sep 2024 00:34:10 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BD=91=E7=BB=9C=E5=BA=93=E5=8F=91=E9=80=81?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E4=BD=BF=E7=94=A8IPacket=EF=BC=8C=E9=83=A8?= =?UTF-8?q?=E5=88=86=E4=BB=A3=E7=A0=81=E5=B0=9A=E6=9C=AA=E5=AE=8C=E6=95=B4?= =?UTF-8?q?=EF=BC=8C=E7=89=B9=E5=88=AB=E6=98=AF=E9=93=BE=E5=BC=8F=E5=8C=85?= =?UTF-8?q?=E5=92=8Cchunk?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NewLife.Core/Data/IPacket.cs | 18 ++++++++ NewLife.Core/Extension/SpanHelper.cs | 54 +++++++++++++++++++++++ NewLife.Core/Http/HttpBase.cs | 9 ++-- NewLife.Core/Http/WebSocket.cs | 3 ++ NewLife.Core/Net/ISocketRemote.cs | 20 +++++++-- NewLife.Core/Net/ITransport.cs | 2 +- NewLife.Core/Net/NetHandlerContext.cs | 3 +- NewLife.Core/Net/SessionBase.cs | 4 +- NewLife.Core/Net/TcpSession.cs | 23 +++++++--- NewLife.Core/Net/UdpServer.cs | 29 +++++++----- NewLife.Core/Net/UdpSession.cs | 2 +- Samples/Zero.Server/ClientTest.cs | 1 + XUnitTest.Core/Http/HttpServerTests.cs | 2 +- XUnitTest.Core/Http/TinyHttpClientTest.cs | 1 + 14 files changed, 141 insertions(+), 30 deletions(-) diff --git a/NewLife.Core/Data/IPacket.cs b/NewLife.Core/Data/IPacket.cs index c97bf8b15..47f01fd16 100644 --- a/NewLife.Core/Data/IPacket.cs +++ b/NewLife.Core/Data/IPacket.cs @@ -122,6 +122,24 @@ public static Stream GetStream(this IPacket pk) return new MemoryStream(pk.GetSpan().ToArray()); } + + /// 返回数据段集合 + /// + public static IList> ToSegments(this IPacket pk) + { + // 初始4元素,优化扩容 + var list = new List>(4); + + for (var p = pk; p != null; p = p.Next) + { + if (p is ArrayPacket ap) + list.Add(new ArraySegment(ap.Buffer, ap.Offset, ap.Length)); + else + list.Add(new ArraySegment(p.GetSpan().ToArray(), 0, p.Length)); + } + + return list; + } } /// 所有权内存包。具有所有权管理,不再使用时释放 diff --git a/NewLife.Core/Extension/SpanHelper.cs b/NewLife.Core/Extension/SpanHelper.cs index 37b838eb2..9e45bac0f 100644 --- a/NewLife.Core/Extension/SpanHelper.cs +++ b/NewLife.Core/Extension/SpanHelper.cs @@ -100,4 +100,58 @@ public static Task WriteAsync(this Stream stream, ReadOnlyMemory buffer, C } }); } + +#if NETFRAMEWORK || NETSTANDARD + /// 去掉前后字符 + /// + /// + /// + /// + public static ReadOnlySpan Trim(this ReadOnlySpan span, T trimElement) where T : IEquatable + { + var start = ClampStart(span, trimElement); + var length = ClampEnd(span, start, trimElement); + return span.Slice(start, length); + } + + /// 去掉前后字符 + /// + /// + /// + /// + public static Span Trim(this Span span, T trimElement) where T : IEquatable + { + var start = ClampStart(span, trimElement); + var length = ClampEnd(span, start, trimElement); + return span.Slice(start, length); + } + + private static Int32 ClampStart(ReadOnlySpan span, T trimElement) where T : IEquatable + { + var i = 0; + for (; i < span.Length; i++) + { + ref var reference = ref trimElement; + if (!reference.Equals(span[i])) + { + break; + } + } + return i; + } + private static Int32 ClampEnd(ReadOnlySpan span, Int32 start, T trimElement) where T : IEquatable + { + var num = span.Length - 1; + while (num >= start) + { + ref var reference = ref trimElement; + if (!reference.Equals(span[num])) + { + break; + } + num--; + } + return num - start + 1; + } +#endif } \ No newline at end of file diff --git a/NewLife.Core/Http/HttpBase.cs b/NewLife.Core/Http/HttpBase.cs index 83f045999..5f1a9d78d 100644 --- a/NewLife.Core/Http/HttpBase.cs +++ b/NewLife.Core/Http/HttpBase.cs @@ -1,4 +1,5 @@ -using System.Text; +using System; +using System.Text; using NewLife.Collections; using NewLife.Data; using NewLife.Serialization; @@ -78,8 +79,8 @@ public Boolean Parse(IPacket pk) var p3 = line.IndexOf((Byte)':'); if (p3 > 0) { - var name = line[..p3].ToStr(); - var value = line[(p3 + 1)..].ToStr(); + var name = line[..p3].Trim((Byte)' ').ToStr(); + var value = line[(p3 + 1)..].Trim((Byte)' ').ToStr(); Headers[name] = value; } } @@ -122,7 +123,7 @@ public Boolean Parse(IPacket pk) public virtual IPacket Build() { var body = Body; - var len = body != null ? body.Length : -1; + var len = body != null ? body.Length : 0; var header = BuildHeader(len); var pk = new ArrayPacket(Encoding.UTF8.GetByteCount(header) + len); diff --git a/NewLife.Core/Http/WebSocket.cs b/NewLife.Core/Http/WebSocket.cs index 7ffec562c..60887b3ee 100644 --- a/NewLife.Core/Http/WebSocket.cs +++ b/NewLife.Core/Http/WebSocket.cs @@ -73,6 +73,9 @@ public void Process(IPacket pk) Handler?.Invoke(this, message); + // 释放内存 + message.Payload?.TryDispose(); + var session = Context?.Connection; var socket = Context?.Socket; if (session == null && socket == null) return; diff --git a/NewLife.Core/Net/ISocketRemote.cs b/NewLife.Core/Net/ISocketRemote.cs index c50b0b121..1393cb2ca 100644 --- a/NewLife.Core/Net/ISocketRemote.cs +++ b/NewLife.Core/Net/ISocketRemote.cs @@ -26,7 +26,7 @@ public interface ISocketRemote : ISocket, IExtend /// /// 数据包 /// 是否成功 - Int32 Send(Packet data); + Int32 Send(IPacket data); #endregion #region 接收 @@ -69,6 +69,20 @@ public interface ISocketRemote : ISocket, IExtend public static class SocketRemoteHelper { #region 发送 + /// 发送数组 + /// + /// + /// + /// + /// + public static Int32 Send(this ISocketRemote session, Byte[] buffer, Int32 offset = 0, Int32 count = -1) + { + if (count < 0) count = buffer.Length - offset; + var pk = new ArrayPacket(buffer, offset, count); + + return session.Send(pk); + } + /// 发送数据流 /// 会话 /// 数据流 @@ -86,7 +100,7 @@ public static Int32 Send(this ISocketRemote session, Stream stream) var count = stream.Read(buffer, 0, buffer.Length); if (count <= 0) break; - var pk = new Packet(buffer, 0, count); + var pk = new ArrayPacket(buffer, 0, count); var count2 = session.Send(pk); if (count2 < 0) break; rs += count2; @@ -158,7 +172,7 @@ public static Int32 SendMessages(this ISocketRemote session, Stream stream) if (rs <= 0) break; // 打包数据,标准编码器StandardCodec将会在头部加上4字节头部,交给下层Tcp发出 - var pk = new Packet(buffer, 0, rs); + var pk = new ArrayPacket(buffer, 0, rs); session.SendMessage(pk); count++; diff --git a/NewLife.Core/Net/ITransport.cs b/NewLife.Core/Net/ITransport.cs index c28adcd1d..ce31caa13 100644 --- a/NewLife.Core/Net/ITransport.cs +++ b/NewLife.Core/Net/ITransport.cs @@ -17,7 +17,7 @@ public interface ITransport : IDisposable /// 写入数据 /// 数据包 - Int32 Send(Packet data); + Int32 Send(IPacket data); /// 读取数据 /// diff --git a/NewLife.Core/Net/NetHandlerContext.cs b/NewLife.Core/Net/NetHandlerContext.cs index 952c57c8f..4247bfb3c 100644 --- a/NewLife.Core/Net/NetHandlerContext.cs +++ b/NewLife.Core/Net/NetHandlerContext.cs @@ -90,11 +90,12 @@ public override Int32 FireWrite(Object message) // 发送一包数据 if (message is Byte[] buf) return session.Send(buf); if (message is Packet pk) return session.Send(pk); + if (message is IPacket ip) return session.Send(ip); if (message is String str) return session.Send(str.GetBytes()); if (message is IAccessor acc) return session.Send(acc.ToPacket()); // 发送一批数据包 - if (message is IEnumerable pks) + if (message is IEnumerable pks) { var rs = 0; foreach (var item in pks) diff --git a/NewLife.Core/Net/SessionBase.cs b/NewLife.Core/Net/SessionBase.cs index 8832f5ecb..dfb27e462 100644 --- a/NewLife.Core/Net/SessionBase.cs +++ b/NewLife.Core/Net/SessionBase.cs @@ -240,7 +240,7 @@ public virtual Boolean Close(String reason) /// /// 数据包 /// 是否成功 - public Int32 Send(Packet data) + public Int32 Send(IPacket data) { if (Disposed) throw new ObjectDisposedException(GetType().Name); if (!Open()) return -1; @@ -254,7 +254,7 @@ public Int32 Send(Packet data) /// /// 数据包 /// 是否成功 - protected abstract Int32 OnSend(Packet data); + protected abstract Int32 OnSend(IPacket data); #endregion 发送 diff --git a/NewLife.Core/Net/TcpSession.cs b/NewLife.Core/Net/TcpSession.cs index 541dfdab5..5132b7665 100644 --- a/NewLife.Core/Net/TcpSession.cs +++ b/NewLife.Core/Net/TcpSession.cs @@ -291,13 +291,14 @@ protected override Boolean OnClose(String reason) /// /// 数据包 /// 是否成功 - protected override Int32 OnSend(Packet pk) + protected override Int32 OnSend(IPacket pk) { - var count = pk.Total; + var count = pk.Length; + var data = pk.GetSpan(); - if (Log != null && Log.Enable && LogSend) WriteLog("Send [{0}]: {1}", count, pk.ToHex(LogDataLength)); + if (Log != null && Log.Enable && LogSend) WriteLog("Send [{0}]: {1}", count, data.ToHex(LogDataLength)); - using var span = Tracer?.NewSpan($"net:{Name}:Send", pk.Total + "", pk.Total); + using var span = Tracer?.NewSpan($"net:{Name}:Send", count + "", count); var rs = count; var sock = Client; @@ -318,7 +319,11 @@ protected override Int32 OnSend(Packet pk) if (count == 0) rs = sock.Send(Pool.Empty); else if (pk.Next == null) - rs = sock.Send(pk.Data, pk.Offset, count, SocketFlags.None); +#if NETCOREAPP || NETSTANDARD2_1 + rs = sock.Send(data); +#else + rs = sock.Send(data.ToArray(), count, SocketFlags.None); +#endif else rs = sock.Send(pk.ToSegments()); } @@ -327,9 +332,13 @@ protected override Int32 OnSend(Packet pk) if (count == 0) _Stream.Write([]); else if (pk.Next == null) - _Stream.Write(pk.Data, pk.Offset, count); +#if NETCOREAPP || NETSTANDARD2_1 + _Stream.Write(data); +#else + _Stream.Write(data.ToArray()); +#endif else - _Stream.Write(pk.ToArray()); + pk.CopyTo(_Stream); } //// 检查返回值 diff --git a/NewLife.Core/Net/UdpServer.cs b/NewLife.Core/Net/UdpServer.cs index cfcdc9905..e8dd73d65 100644 --- a/NewLife.Core/Net/UdpServer.cs +++ b/NewLife.Core/Net/UdpServer.cs @@ -116,7 +116,7 @@ protected override Boolean OnClose(String reason) var remote = Remote; if (remote != null && !remote.Address.IsAny() && remote.Port != 0) { - Send(Pool.Empty); + this.Send(Pool.Empty); } Client = null; @@ -145,13 +145,14 @@ protected override Boolean OnClose(String reason) /// /// 数据包 /// 是否成功 - protected override Int32 OnSend(Packet pk) => OnSend(pk, Remote.EndPoint); + protected override Int32 OnSend(IPacket pk) => OnSend(pk, Remote.EndPoint); - internal Int32 OnSend(Packet pk, IPEndPoint remote) + internal Int32 OnSend(IPacket pk, IPEndPoint remote) { - var count = pk.Total; + var count = pk.Length; + var data = pk.GetSpan(); - using var span = Tracer?.NewSpan($"net:{Name}:Send", pk.Total + "", pk.Total); + using var span = Tracer?.NewSpan($"net:{Name}:Send", count + "", count); try { @@ -161,22 +162,30 @@ internal Int32 OnSend(Packet pk, IPEndPoint remote) { if (sock.Connected && !sock.EnableBroadcast) { - if (Log.Enable && LogSend) WriteLog("Send [{0}]: {1}", count, pk.ToHex(LogDataLength)); + if (Log.Enable && LogSend) WriteLog("Send [{0}]: {1}", count, data.ToHex(LogDataLength)); if (pk.Next == null) - rs = sock.Send(pk.Data, pk.Offset, count, SocketFlags.None); +#if NETCOREAPP || NETSTANDARD2_1 + rs = sock.Send(data); +#else + rs = sock.Send(data.ToArray(), count, SocketFlags.None); +#endif else rs = sock.Send(pk.ToSegments(), SocketFlags.None); } else { sock.CheckBroadcast(remote.Address); - if (Log.Enable && LogSend) WriteLog("Send {2} [{0}]: {1}", count, pk.ToHex(LogDataLength), remote); + if (Log.Enable && LogSend) WriteLog("Send {2} [{0}]: {1}", count, data.ToHex(LogDataLength), remote); if (pk.Next == null) - rs = sock.SendTo(pk.Data, pk.Offset, count, SocketFlags.None, remote); +#if NET6_0_OR_GREATER + rs = sock.SendTo(data, remote); +#else + rs = sock.SendTo(data.ToArray(), 0, count, SocketFlags.None, remote); +#endif else - rs = sock.SendTo(pk.ToArray(), 0, count, SocketFlags.None, remote); + rs = sock.SendTo(data.ToArray(), 0, count, SocketFlags.None, remote); } } diff --git a/NewLife.Core/Net/UdpSession.cs b/NewLife.Core/Net/UdpSession.cs index fb2a8d355..ff47cde7e 100644 --- a/NewLife.Core/Net/UdpSession.cs +++ b/NewLife.Core/Net/UdpSession.cs @@ -135,7 +135,7 @@ protected override void Dispose(Boolean disposing) /// /// /// - public Int32 Send(Packet data) + public Int32 Send(IPacket data) { if (Disposed) throw new ObjectDisposedException(GetType().Name); diff --git a/Samples/Zero.Server/ClientTest.cs b/Samples/Zero.Server/ClientTest.cs index b4f74d9a4..a99732111 100644 --- a/Samples/Zero.Server/ClientTest.cs +++ b/Samples/Zero.Server/ClientTest.cs @@ -1,6 +1,7 @@ using System.Net.Sockets; using System.Text; using NewLife; +using NewLife.Data; using NewLife.Log; using NewLife.Net; diff --git a/XUnitTest.Core/Http/HttpServerTests.cs b/XUnitTest.Core/Http/HttpServerTests.cs index 2fb8b8bf3..ddece46e1 100644 --- a/XUnitTest.Core/Http/HttpServerTests.cs +++ b/XUnitTest.Core/Http/HttpServerTests.cs @@ -134,7 +134,7 @@ public void ProcessRequest(IHttpContext context) // 数据部分,链式 var pk = context.Request.Body; - Assert.Equal(8 * 1024 * 2, pk.Total); + Assert.Equal(8 * 1024 * 2, pk.Length); var name = context.Parameters["name"]; var html = $"

你好,{name}

"; diff --git a/XUnitTest.Core/Http/TinyHttpClientTest.cs b/XUnitTest.Core/Http/TinyHttpClientTest.cs index dfe20e0fc..9678eddb0 100644 --- a/XUnitTest.Core/Http/TinyHttpClientTest.cs +++ b/XUnitTest.Core/Http/TinyHttpClientTest.cs @@ -3,6 +3,7 @@ using NewLife.Http; using NewLife.Log; using Xunit; +using NewLife.Data; namespace XUnitTest.Http;