NewLife/XCoder

升级组件引用
智能大石头 authored at 2025-05-14 18:18:23
98352d5
Tree
1 Parent(s) 14b890f
Summary: 15 changed files with 589 additions and 598 deletions.
Modified +135 -136
Modified +1 -1
Modified +9 -7
Modified +3 -2
Modified +406 -396
Modified +17 -18
Modified +2 -2
Modified +1 -0
Modified +1 -1
Modified +1 -0
Modified +7 -4
Modified +2 -1
Modified +1 -1
Modified +1 -1
Modified +2 -28
Modified +135 -136
diff --git a/XCoder/Protocols/ModbusMessage.cs b/XCoder/Protocols/ModbusMessage.cs
index 38bf932..69d2928 100644
--- a/XCoder/Protocols/ModbusMessage.cs
+++ b/XCoder/Protocols/ModbusMessage.cs
@@ -4,166 +4,165 @@ using System.Runtime.Serialization;
 using NewLife.Data;
 using NewLife.Serialization;
 
-namespace NewLife.IoT.Protocols
+namespace NewLife.IoT.Protocols;
+
+public class ModbusMessage : IAccessor
 {
-    public class ModbusMessage : IAccessor
-    {
-        #region 属性
-        /// <summary>是否响应</summary>
-        [IgnoreDataMember]
-        public Boolean Reply { get; set; }
+    #region 属性
+    /// <summary>是否响应</summary>
+    [IgnoreDataMember]
+    public Boolean Reply { get; set; }
 
-        /// <summary>事务编号</summary>
-        public UInt16 TransactionId { get; set; }
+    /// <summary>事务编号</summary>
+    public UInt16 TransactionId { get; set; }
 
-        /// <summary>协议</summary>
-        public UInt16 ProtocolId { get; set; }
+    /// <summary>协议</summary>
+    public UInt16 ProtocolId { get; set; }
 
-        /// <summary>站号</summary>
-        public Byte Host { get; set; }
+    /// <summary>站号</summary>
+    public Byte Host { get; set; }
 
-        /// <summary>操作码</summary>
-        public FunctionCodes Code { get; set; }
+    /// <summary>操作码</summary>
+    public FunctionCodes Code { get; set; }
 
-        /// <summary>地址。请求中使用</summary>
-        public UInt16 Address { get; set; }
+    /// <summary>地址。请求中使用</summary>
+    public UInt16 Address { get; set; }
 
-        /// <summary>个数</summary>
-        public UInt16 Count { get; set; }
+    /// <summary>个数</summary>
+    public UInt16 Count { get; set; }
 
-        /// <summary>负载数据。响应中使用</summary>
-        [IgnoreDataMember]
-        public Packet Payload { get; set; }
-        #endregion
+    /// <summary>负载数据。响应中使用</summary>
+    [IgnoreDataMember]
+    public Packet Payload { get; set; }
+    #endregion
 
-        #region 构造
-        public override String ToString()
+    #region 构造
+    public override String ToString()
+    {
+        if (!Reply)
         {
-            if (!Reply)
-            {
-                if (Payload == null)
-                    return $"{Code} ({Address}, {Count})";
-                else
-                    return $"{Code} ({Address}={Payload.ToHex()})";
-            }
+            if (Payload == null)
+                return $"{Code} ({Address}, {Count})";
             else
-                return $"{Code} {Payload.ToHex()}";
+                return $"{Code} ({Address}={Payload.ToHex()})";
         }
-        #endregion
-
-        #region 方法
-        /// <summary>读取</summary>
-        /// <param name="stream"></param>
-        /// <param name="context"></param>
-        /// <returns></returns>
-        public Boolean Read(Stream stream, Object context)
+        else
+            return $"{Code} {Payload.ToHex()}";
+    }
+    #endregion
+
+    #region 方法
+    /// <summary>读取</summary>
+    /// <param name="stream"></param>
+    /// <param name="context"></param>
+    /// <returns></returns>
+    public Boolean Read(Stream stream, Object context)
+    {
+        var binary = context as Binary ?? new Binary { Stream = stream, IsLittleEndian = false };
+
+        TransactionId = binary.Read<UInt16>();
+        ProtocolId = binary.Read<UInt16>();
+        var len = binary.Read<UInt16>();
+        if (len < 1 + 1 + 1) return false;
+
+        Host = binary.ReadByte();
+        Code = (FunctionCodes)binary.ReadByte();
+
+        len -= 2;
+        if (!Reply)
         {
-            var binary = context as Binary ?? new Binary { Stream = stream, IsLittleEndian = false };
-
-            TransactionId = binary.Read<UInt16>();
-            ProtocolId = binary.Read<UInt16>();
-            var len = binary.Read<UInt16>();
-            if (len < 1 + 1 + 1) return false;
-
-            Host = binary.ReadByte();
-            Code = (FunctionCodes)binary.ReadByte();
-
-            len -= 2;
-            if (!Reply)
-            {
-                Address = binary.Read<UInt16>();
-                if (len == 4)
-                    Count = binary.Read<UInt16>();
-                else
-                    Payload = binary.ReadBytes(len - 2);
-            }
-            else if (len >= 1)
-            {
-                var len2 = binary.ReadByte();
-                if (len2 <= len - 1) Payload = binary.ReadBytes(len2);
-            }
-
-            return true;
+            Address = binary.Read<UInt16>();
+            if (len == 4)
+                Count = binary.Read<UInt16>();
+            else
+                Payload = binary.ReadBytes(len - 2);
         }
-
-        /// <summary>解析消息</summary>
-        /// <param name="pk"></param>
-        /// <returns></returns>
-        public static ModbusMessage Read(Packet pk, Boolean reply = false)
+        else if (len >= 1)
         {
-            var msg = new ModbusMessage { Reply = reply };
-            if (msg.Read(pk.GetStream(), null)) return msg;
-
-            return null;
+            var len2 = binary.ReadByte();
+            if (len2 <= len - 1) Payload = binary.ReadBytes(len2);
         }
 
-        /// <summary>写入消息到数据流</summary>
-        /// <param name="stream"></param>
-        /// <param name="context"></param>
-        /// <returns></returns>
-        public Boolean Write(Stream stream, Object context)
-        {
-            var binary = context as Binary ?? new Binary { Stream = stream, IsLittleEndian = false };
+        return true;
+    }
 
-            binary.Write(TransactionId);
-            binary.Write(ProtocolId);
+    /// <summary>解析消息</summary>
+    /// <param name="pk"></param>
+    /// <returns></returns>
+    public static ModbusMessage Read(IPacket pk, Boolean reply = false)
+    {
+        var msg = new ModbusMessage { Reply = reply };
+        if (msg.Read(pk.GetStream(), null)) return msg;
 
-            var pk = Payload;
-            var len = 1 + 1;
-            if (!Reply)
-                len += 2 + (pk?.Total ?? 2);
-            else
-                len += 1 + (pk?.Total ?? 0);
-            binary.Write((UInt16)len);
-
-            binary.Write(Host);
-            binary.Write((Byte)Code);
-
-            if (!Reply)
-            {
-                binary.Write(Address);
-                if (pk != null)
-                    binary.Write(pk.Data, pk.Offset, pk.Count);
-                else
-                    binary.Write(Count);
-            }
+        return null;
+    }
+
+    /// <summary>写入消息到数据流</summary>
+    /// <param name="stream"></param>
+    /// <param name="context"></param>
+    /// <returns></returns>
+    public Boolean Write(Stream stream, Object context)
+    {
+        var binary = context as Binary ?? new Binary { Stream = stream, IsLittleEndian = false };
+
+        binary.Write(TransactionId);
+        binary.Write(ProtocolId);
+
+        var pk = Payload;
+        var len = 1 + 1;
+        if (!Reply)
+            len += 2 + (pk?.Total ?? 2);
+        else
+            len += 1 + (pk?.Total ?? 0);
+        binary.Write((UInt16)len);
+
+        binary.Write(Host);
+        binary.Write((Byte)Code);
+
+        if (!Reply)
+        {
+            binary.Write(Address);
+            if (pk != null)
+                binary.Write(pk.Data, pk.Offset, pk.Count);
             else
-            {
-                var len2 = (pk?.Total ?? 0);
-                binary.Write((Byte)len2);
-                if (pk != null)
-                    binary.Write(pk.Data, pk.Offset, pk.Count);
-            }
-
-            return true;
+                binary.Write(Count);
         }
-
-        /// <summary>消息转数据包</summary>
-        /// <returns></returns>
-        public Packet ToPacket()
+        else
         {
-            var ms = new MemoryStream();
-            Write(ms, null);
-
-            ms.Position = 0;
-            return new Packet(ms);
+            var len2 = (pk?.Total ?? 0);
+            binary.Write((Byte)len2);
+            if (pk != null)
+                binary.Write(pk.Data, pk.Offset, pk.Count);
         }
 
-        public ModbusMessage CreateReply()
+        return true;
+    }
+
+    /// <summary>消息转数据包</summary>
+    /// <returns></returns>
+    public Packet ToPacket()
+    {
+        var ms = new MemoryStream();
+        Write(ms, null);
+
+        ms.Position = 0;
+        return new Packet(ms);
+    }
+
+    public ModbusMessage CreateReply()
+    {
+        if (Reply) throw new InvalidOperationException();
+
+        var msg = new ModbusMessage
         {
-            if (Reply) throw new InvalidOperationException();
-
-            var msg = new ModbusMessage
-            {
-                Reply = true,
-                TransactionId = TransactionId,
-                ProtocolId = ProtocolId,
-                Host = Host,
-                Code = Code,
-            };
-
-            return msg;
-        }
-        #endregion
+            Reply = true,
+            TransactionId = TransactionId,
+            ProtocolId = ProtocolId,
+            Host = Host,
+            Code = Code,
+        };
+
+        return msg;
     }
+    #endregion
 }
\ No newline at end of file
Modified +1 -1
diff --git a/XCoder/Protocols/ModbusTcp.cs b/XCoder/Protocols/ModbusTcp.cs
index 9953451..2455d59 100644
--- a/XCoder/Protocols/ModbusTcp.cs
+++ b/XCoder/Protocols/ModbusTcp.cs
@@ -108,7 +108,7 @@ namespace NewLife.IoT.Protocols
 
                 if (span2 != null) span2.Tag = buf.ToHex();
 
-                var rs = ModbusMessage.Read(buf, true);
+                var rs = ModbusMessage.Read((ArrayPacket)buf, true);
                 if (rs == null) return null;
 
                 WriteLog("<= {0}", rs);
Modified +9 -7
diff --git a/XCoder/XCoder.csproj b/XCoder/XCoder.csproj
index 285e330..193b798 100644
--- a/XCoder/XCoder.csproj
+++ b/XCoder/XCoder.csproj
@@ -13,6 +13,8 @@
     <ApplicationIcon>leaf.ico</ApplicationIcon>
     <LangVersion>latest</LangVersion>
     <TargetFrameworkProfile />
+    <ImplicitUsings>enable</ImplicitUsings>
+    <LangVersion>latest</LangVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
@@ -384,25 +386,25 @@
   </ItemGroup>
   <ItemGroup>
     <PackageReference Include="NewLife.Core">
-      <Version>10.10.2024.803</Version>
+      <Version>11.5.2025.501</Version>
     </PackageReference>
     <PackageReference Include="NewLife.Map">
-      <Version>2.6.2024.801</Version>
+      <Version>2.6.2025.305</Version>
     </PackageReference>
     <PackageReference Include="NewLife.MQTT">
-      <Version>2.0.2024.822-beta1012</Version>
+      <Version>2.0.2025.415</Version>
     </PackageReference>
     <PackageReference Include="NewLife.Net">
-      <Version>4.3.2024.822-beta1011</Version>
+      <Version>4.4.2025.305</Version>
     </PackageReference>
     <PackageReference Include="NewLife.Redis">
-      <Version>5.7.2024.801</Version>
+      <Version>6.2.2025.503</Version>
     </PackageReference>
     <PackageReference Include="NewLife.Stardust">
-      <Version>3.0.2024.806</Version>
+      <Version>3.3.2025.506</Version>
     </PackageReference>
     <PackageReference Include="NewLife.XCode">
-      <Version>11.15.2024.806</Version>
+      <Version>11.19.2025.501</Version>
     </PackageReference>
     <PackageReference Include="SSH.NET">
       <Version>2020.0.2</Version>
Modified +3 -2
diff --git a/XCoder/XCom/SerialPortList.cs b/XCoder/XCom/SerialPortList.cs
index 7a4e5ff..5007c27 100644
--- a/XCoder/XCom/SerialPortList.cs
+++ b/XCoder/XCom/SerialPortList.cs
@@ -6,6 +6,7 @@ using System.IO;
 using System.IO.Ports;
 using System.Text;
 using System.Windows.Forms;
+using NewLife.Data;
 using NewLife.Log;
 using NewLife.Net;
 using NewLife.Threading;
@@ -87,7 +88,7 @@ namespace NewLife.Windows
 
             //cbEncoding.DataSource = new String[] { Encoding.UTF8.WebName, Encoding.ASCII.WebName, Encoding.UTF8.WebName };
             // 添加编码子菜单
-            var encs = new Encoding[] { Encoding.UTF8, Encoding.ASCII, Encoding.UTF7, Encoding.Unicode, Encoding.BigEndianUnicode, Encoding.UTF32,Encoding.GetEncoding("GB2312") };
+            var encs = new Encoding[] { Encoding.UTF8, Encoding.ASCII, Encoding.UTF7, Encoding.Unicode, Encoding.BigEndianUnicode, Encoding.UTF32, Encoding.GetEncoding("GB2312") };
             var list = new List<Encoding>(encs);
             // 暂时不用这么多编码
             //list.AddRange(Encoding.GetEncodings().Select(e => e.GetEncoding()).Where(e => !encs.Contains(e)));
@@ -449,7 +450,7 @@ namespace NewLife.Windows
         StreamReader _reader;
         void OnReceived(Object sender, ReceivedEventArgs e)
         {
-            var data = e.Packet.ReadBytes();
+            var data = e.Packet.ReadBytes(0, -1);
             if (data == null || data.Length < 1) return;
 
             BytesOfReceived += data.Length;
Modified +406 -396
diff --git a/XCoder/XCom/SerialTransport.cs b/XCoder/XCom/SerialTransport.cs
index c3d432a..206b5d3 100644
--- a/XCoder/XCom/SerialTransport.cs
+++ b/XCoder/XCom/SerialTransport.cs
@@ -9,522 +9,532 @@ using NewLife.Data;
 using NewLife.Log;
 using NewLife.Threading;
 
-namespace NewLife.Net
+namespace NewLife.Net;
+
+/// <summary>串口传输</summary>
+/// <example>
+/// 标准例程:
+/// <code>
+/// var st = new SerialTransport();
+/// st.PortName = "COM65";  // 通讯口
+/// st.FrameSize = 16;      // 数据帧大小
+/// 
+/// st.Received += (s, e) =>
+/// {
+///     Console.WriteLine("收到 {0}", e.ToHex());
+/// };
+/// // 开始异步操作
+/// st.Open();
+/// 
+/// //var buf = "01080000801A".ToHex();
+/// var buf = "0111C02C".ToHex();
+/// for (int i = 0; i &lt; 100; i++)
+/// {
+///     Console.WriteLine("发送 {0}", buf.ToHex());
+///     st.Send(buf);
+/// 
+///     Thread.Sleep(1000);
+/// }
+/// </code>
+/// </example>
+public class SerialTransport : DisposeBase, ITransport
 {
-    /// <summary>串口传输</summary>
-    /// <example>
-    /// 标准例程:
-    /// <code>
-    /// var st = new SerialTransport();
-    /// st.PortName = "COM65";  // 通讯口
-    /// st.FrameSize = 16;      // 数据帧大小
-    /// 
-    /// st.Received += (s, e) =>
-    /// {
-    ///     Console.WriteLine("收到 {0}", e.ToHex());
-    /// };
-    /// // 开始异步操作
-    /// st.Open();
-    /// 
-    /// //var buf = "01080000801A".ToHex();
-    /// var buf = "0111C02C".ToHex();
-    /// for (int i = 0; i &lt; 100; i++)
-    /// {
-    ///     Console.WriteLine("发送 {0}", buf.ToHex());
-    ///     st.Send(buf);
-    /// 
-    ///     Thread.Sleep(1000);
-    /// }
-    /// </code>
-    /// </example>
-    public class SerialTransport : DisposeBase, ITransport
+    #region 属性
+    private SerialPort _Serial;
+    /// <summary>串口对象</summary>
+    public SerialPort Serial
     {
-        #region 属性
-        private SerialPort _Serial;
-        /// <summary>串口对象</summary>
-        public SerialPort Serial
+        get { return _Serial; }
+        set
         {
-            get { return _Serial; }
-            set
+            _Serial = value;
+            if (_Serial != null)
             {
-                _Serial = value;
-                if (_Serial != null)
-                {
-                    PortName = _Serial.PortName;
-                    BaudRate = _Serial.BaudRate;
-                    Parity = _Serial.Parity;
-                    DataBits = _Serial.DataBits;
-                    StopBits = _Serial.StopBits;
-                }
+                PortName = _Serial.PortName;
+                BaudRate = _Serial.BaudRate;
+                Parity = _Serial.Parity;
+                DataBits = _Serial.DataBits;
+                StopBits = _Serial.StopBits;
             }
         }
+    }
 
-        /// <summary>端口名称。默认COM1</summary>
-        public String PortName { get; set; } = "COM1";
+    /// <summary>端口名称。默认COM1</summary>
+    public String PortName { get; set; } = "COM1";
 
-        /// <summary>波特率。默认115200</summary>
-        public Int32 BaudRate { get; set; } = 115200;
+    /// <summary>波特率。默认115200</summary>
+    public Int32 BaudRate { get; set; } = 115200;
 
-        /// <summary>奇偶校验位。默认None</summary>
-        public Parity Parity { get; set; } = Parity.None;
+    /// <summary>奇偶校验位。默认None</summary>
+    public Parity Parity { get; set; } = Parity.None;
 
-        /// <summary>数据位。默认8</summary>
-        public Int32 DataBits { get; set; } = 8;
+    /// <summary>数据位。默认8</summary>
+    public Int32 DataBits { get; set; } = 8;
 
-        /// <summary>停止位。默认One</summary>
-        public StopBits StopBits { get; set; } = StopBits.One;
+    /// <summary>停止位。默认One</summary>
+    public StopBits StopBits { get; set; } = StopBits.One;
 
-        /// <summary>超时时间。超过该大小未收到数据,说明是另一帧。默认10ms</summary>
-        public Int32 Timeout { get; set; } = 10;
+    /// <summary>超时时间。超过该大小未收到数据,说明是另一帧。默认10ms</summary>
+    public Int32 Timeout { get; set; } = 10;
 
-        private String _Description;
-        /// <summary>描述信息</summary>
-        public String Description
+    private String _Description;
+    /// <summary>描述信息</summary>
+    public String Description
+    {
+        get
         {
-            get
+            if (_Description == null)
             {
-                if (_Description == null)
-                {
-                    var dic = GetNames();
-                    if (!dic.TryGetValue(PortName, out _Description))
-                        _Description = "";
-                }
-                return _Description;
+                var dic = GetNames();
+                if (!dic.TryGetValue(PortName, out _Description))
+                    _Description = "";
             }
+            return _Description;
         }
+    }
 
-        ///// <summary>粘包处理接口</summary>
-        //public IPacket Packet { get; set; }
+    ///// <summary>粘包处理接口</summary>
+    //public IPacket Packet { get; set; }
 
-        /// <summary>字节超时。数据包间隔,默认20ms</summary>
-        public Int32 ByteTimeout { get; set; } = 20;
-        #endregion
+    /// <summary>字节超时。数据包间隔,默认20ms</summary>
+    public Int32 ByteTimeout { get; set; } = 20;
+    #endregion
 
-        #region 构造
-        /// <summary>串口传输</summary>
-        public SerialTransport()
-        {
-            // 每隔一段时间检查一次串口是否已经关闭,如果串口已经不存在,则关闭该传输口
-            timer = new TimerX(CheckDisconnect, null, 3000, 3000) { Async = true };
-        }
+    #region 构造
+    /// <summary>串口传输</summary>
+    public SerialTransport()
+    {
+        // 每隔一段时间检查一次串口是否已经关闭,如果串口已经不存在,则关闭该传输口
+        timer = new TimerX(CheckDisconnect, null, 3000, 3000) { Async = true };
+    }
 
-        /// <summary>销毁</summary>
-        /// <param name="disposing"></param>
-        //protected override void Dispose(Boolean disposing)
-        //{
-        //    base.Dispose(disposing);
-
-        //    try
-        //    {
-        //        if (Serial != null) Close();
-        //        if (timer != null) timer.Dispose();
-        //    }
-        //    catch { }
-        //}
-        #endregion
-
-        #region 方法
-        /// <summary>确保创建</summary>
-        public virtual void EnsureCreate()
+    /// <summary>销毁</summary>
+    /// <param name="disposing"></param>
+    //protected override void Dispose(Boolean disposing)
+    //{
+    //    base.Dispose(disposing);
+
+    //    try
+    //    {
+    //        if (Serial != null) Close();
+    //        if (timer != null) timer.Dispose();
+    //    }
+    //    catch { }
+    //}
+    #endregion
+
+    #region 方法
+    /// <summary>确保创建</summary>
+    public virtual void EnsureCreate()
+    {
+        if (Serial == null)
         {
-            if (Serial == null)
-            {
-                Serial = new SerialPort(PortName, BaudRate, Parity, DataBits, StopBits);
+            Serial = new SerialPort(PortName, BaudRate, Parity, DataBits, StopBits);
 
-                _Description = null;
-            }
+            _Description = null;
         }
+    }
+
+    /// <summary>打开</summary>
+    public virtual Boolean Open()
+    {
+        EnsureCreate();
 
-        /// <summary>打开</summary>
-        public virtual Boolean Open()
+        if (!Serial.IsOpen)
         {
-            EnsureCreate();
+            Serial.Open();
+            if (Received != null) Serial.DataReceived += DataReceived;
+        }
 
-            if (!Serial.IsOpen)
-            {
-                Serial.Open();
-                if (Received != null) Serial.DataReceived += DataReceived;
-            }
+        return true;
+    }
+
+    /// <summary>关闭</summary>
+    public virtual Boolean Close()
+    {
+        // 关闭时必须清空,否则更换属性后再次打开也无法改变属性
+        var sp = Serial;
+        if (sp != null)
+        {
+            Serial = null;
+            if (Received != null) sp.DataReceived -= DataReceived;
+            if (sp.IsOpen) sp.Close();
 
-            return true;
+            OnDisconnect();
         }
 
-        /// <summary>关闭</summary>
-        public virtual Boolean Close()
-        {
-            // 关闭时必须清空,否则更换属性后再次打开也无法改变属性
-            var sp = Serial;
-            if (sp != null)
-            {
-                Serial = null;
-                if (Received != null) sp.DataReceived -= DataReceived;
-                if (sp.IsOpen) sp.Close();
+        return true;
+    }
+    #endregion
 
-                OnDisconnect();
-            }
+    #region 发送
+    /// <summary>写入数据</summary>
+    /// <param name="pk">数据包</param>
+    public virtual Int32 Send(IPacket pk)
+    {
+        if (!Open()) return -1;
 
-            return true;
-        }
-        #endregion
+        WriteLog("Send:{0}", pk.ToHex());
 
-        #region 发送
-        /// <summary>写入数据</summary>
-        /// <param name="pk">数据包</param>
-        public virtual Int32 Send(Packet pk)
+        var sp = Serial;
+        lock (sp)
         {
-            if (!Open()) return -1;
+            if (pk.TryGetArray(out var arr))
+                sp.Write(arr.Array, arr.Offset, arr.Count);
+            else
+                sp.Write(pk.ToArray(), 0, pk.Total);
+        }
 
-            WriteLog("Send:{0}", pk.ToHex());
+        return pk.Total;
+    }
 
-            var sp = Serial;
-            lock (sp)
-            {
-                sp.Write(pk.Data, pk.Offset, pk.Count);
-            }
+    public Int32 Send(Byte[] buffer) => Send(new ArrayPacket(buffer));
 
-            return pk.Total;
-        }
+    /// <summary>异步发送数据并等待响应</summary>
+    /// <param name="pk"></param>
+    /// <returns></returns>
+    public virtual async Task<IOwnerPacket> SendAsync(IPacket pk)
+    {
+        if (!Open()) return null;
 
-        /// <summary>异步发送数据并等待响应</summary>
-        /// <param name="pk"></param>
-        /// <returns></returns>
-        public virtual async Task<Packet> SendAsync(Packet pk)
-        {
-            if (!Open()) return null;
+        //if (Packet == null) Packet = new PacketProvider();
 
-            //if (Packet == null) Packet = new PacketProvider();
+        //var task = Packet.Add(pk, null, Timeout);
 
-            //var task = Packet.Add(pk, null, Timeout);
+        _Source = new TaskCompletionSource<IOwnerPacket>();
 
-            _Source = new TaskCompletionSource<Packet>();
+        if (pk != null)
+        {
+            WriteLog("SendAsync:{0}", pk.ToHex());
 
-            if (pk != null)
+            // 发送数据
+            var sp = Serial;
+            lock (sp)
             {
-                WriteLog("SendAsync:{0}", pk.ToHex());
-
-                // 发送数据
-                Serial.Write(pk.Data, pk.Offset, pk.Count);
+                if (pk.TryGetArray(out var arr))
+                    sp.Write(arr.Array, arr.Offset, arr.Count);
+                else
+                    sp.Write(pk.ToArray(), 0, pk.Total);
             }
-
-            return await _Source.Task;
         }
 
-        /// <summary>接收数据</summary>
-        /// <returns></returns>
-        public virtual Packet Receive()
-        {
-            if (!Open()) return null;
+        return await _Source.Task;
+    }
 
-            var task = SendAsync(null);
-            if (Timeout > 0 && !task.Wait(Timeout)) return null;
+    /// <summary>接收数据</summary>
+    /// <returns></returns>
+    public virtual IOwnerPacket Receive()
+    {
+        if (!Open()) return null;
 
-            return task.Result;
-        }
-        #endregion
+        var task = SendAsync(null);
+        if (Timeout > 0 && !task.Wait(Timeout)) return null;
 
-        #region 异步接收
-        void DataReceived(Object sender, SerialDataReceivedEventArgs e)
+        return task.Result;
+    }
+    #endregion
+
+    #region 异步接收
+    void DataReceived(Object sender, SerialDataReceivedEventArgs e)
+    {
+        // 发送者必须保持一定间隔,每个报文不能太大,否则会因为粘包拆包而出错
+        try
         {
-            // 发送者必须保持一定间隔,每个报文不能太大,否则会因为粘包拆包而出错
-            try
+            var sp = sender as SerialPort;
+            WaitMore();
+            if (sp.BytesToRead > 0)
             {
-                var sp = sender as SerialPort;
-                WaitMore();
-                if (sp.BytesToRead > 0)
-                {
-                    var buf = new Byte[sp.BytesToRead];
+                //var buf = new Byte[sp.BytesToRead];
 
-                    var count = sp.Read(buf, 0, buf.Length);
-                    //if (count != buf.Length) buf = buf.ReadBytes(0, count);
-                    //var ms = new MemoryStream(buf, 0, count, false);
-                    var pk = new Packet(buf, 0, count);
+                var pk = new OwnerPacket(sp.BytesToRead);
+                var count = sp.Read(pk.Buffer, pk.Offset, pk.Length);
+                pk.Resize(count);
 
-                    ProcessReceive(pk);
-                }
-            }
-            catch (Exception ex)
-            {
-                //WriteLog("Error " + ex.Message);
-                if (Log != null) Log.Error("DataReceived Error {0}", ex.Message);
+                ProcessReceive(pk);
             }
         }
-
-        void WaitMore()
+        catch (Exception ex)
         {
-            var sp = Serial;
-
-            var ms = ByteTimeout;
-            var end = DateTime.Now.AddMilliseconds(ms);
-            var count = sp.BytesToRead;
-            while (sp.IsOpen && end > DateTime.Now)
-            {
-                //Thread.SpinWait(1);
-                Thread.Sleep(ms);
-                if (count != sp.BytesToRead)
-                {
-                    end = DateTime.Now.AddMilliseconds(ms);
-                    count = sp.BytesToRead;
-                }
-            }
+            //WriteLog("Error " + ex.Message);
+            if (Log != null) Log.Error("DataReceived Error {0}", ex.Message);
         }
+    }
+
+    void WaitMore()
+    {
+        var sp = Serial;
 
-        void ProcessReceive(Packet pk)
+        var ms = ByteTimeout;
+        var end = DateTime.Now.AddMilliseconds(ms);
+        var count = sp.BytesToRead;
+        while (sp.IsOpen && end > DateTime.Now)
         {
-            try
-            {
-                //if (Packet == null)
-                OnReceive(pk);
-                //else
-                //{
-                //    // 拆包,多个包多次调用处理程序
-                //    foreach (var msg in Packet.Parse(pk))
-                //    {
-                //        OnReceive(msg);
-                //    }
-                //}
-            }
-            catch (Exception ex)
+            //Thread.SpinWait(1);
+            Thread.Sleep(ms);
+            if (count != sp.BytesToRead)
             {
-                if (!ex.IsDisposed()) Log.Error("{0}.OnReceive {1}", PortName, ex.Message);
+                end = DateTime.Now.AddMilliseconds(ms);
+                count = sp.BytesToRead;
             }
         }
+    }
 
-        private TaskCompletionSource<Packet> _Source;
-        /// <summary>处理收到的数据。默认匹配同步接收委托</summary>
-        /// <param name="pk"></param>
-        internal virtual void OnReceive(Packet pk)
+    void ProcessReceive(IOwnerPacket pk)
+    {
+        try
+        {
+            //if (Packet == null)
+            OnReceive(pk);
+            //else
+            //{
+            //    // 拆包,多个包多次调用处理程序
+            //    foreach (var msg in Packet.Parse(pk))
+            //    {
+            //        OnReceive(msg);
+            //    }
+            //}
+        }
+        catch (Exception ex)
         {
-            //// 同步匹配
-            //if (Packet != null && Packet.Match(pk, null)) return;
+            if (!ex.IsDisposed()) Log.Error("{0}.OnReceive {1}", PortName, ex.Message);
+        }
+    }
 
-            if (_Source != null)
-            {
-                _Source.SetResult(pk);
-                _Source = null;
-                return;
-            }
+    private TaskCompletionSource<IOwnerPacket> _Source;
+    /// <summary>处理收到的数据。默认匹配同步接收委托</summary>
+    /// <param name="pk"></param>
+    internal virtual void OnReceive(IOwnerPacket pk)
+    {
+        //// 同步匹配
+        //if (Packet != null && Packet.Match(pk, null)) return;
 
-            // 触发事件
-            Received?.Invoke(this, new ReceivedEventArgs { Packet = pk });
+        if (_Source != null)
+        {
+            _Source.SetResult(pk);
+            _Source = null;
+            return;
         }
 
-        /// <summary>数据到达事件</summary>
-        public event EventHandler<ReceivedEventArgs> Received;
-        #endregion
+        // 触发事件
+        Received?.Invoke(this, new ReceivedEventArgs { Packet = pk });
+    }
+
+    /// <summary>数据到达事件</summary>
+    public event EventHandler<ReceivedEventArgs> Received;
+    #endregion
 
-        #region 自动检测串口断开
-        /// <summary>断开时触发,可能是人为断开,也可能是串口链路断开</summary>
-        public event EventHandler Disconnected;
+    #region 自动检测串口断开
+    /// <summary>断开时触发,可能是人为断开,也可能是串口链路断开</summary>
+    public event EventHandler Disconnected;
 
-        Boolean isInEvent;
-        void OnDisconnect()
+    Boolean isInEvent;
+    void OnDisconnect()
+    {
+        if (Disconnected != null)
         {
-            if (Disconnected != null)
+            // 判断是否在事件中,避免外部在断开时间中调用Close造成死循环
+            if (!isInEvent)
             {
-                // 判断是否在事件中,避免外部在断开时间中调用Close造成死循环
-                if (!isInEvent)
-                {
-                    isInEvent = true;
+                isInEvent = true;
 
-                    Disconnected(this, EventArgs.Empty);
+                Disconnected(this, EventArgs.Empty);
 
-                    isInEvent = false;
-                }
+                isInEvent = false;
             }
         }
+    }
 
-        TimerX timer;
-        /// <summary>检查串口是否已经断开</summary>
-        /// <remarks>
-        /// FX串口异步操作有严重的泄漏缺陷,如果外部硬件长时间断开,
-        /// SerialPort.IsOpen检测不到,并且会无限大占用内存。
-        /// </remarks>
-        /// <param name="state"></param>
-        void CheckDisconnect(Object state)
-        {
-            if (String.IsNullOrEmpty(PortName) || Serial == null || !Serial.IsOpen) return;
+    TimerX timer;
+    /// <summary>检查串口是否已经断开</summary>
+    /// <remarks>
+    /// FX串口异步操作有严重的泄漏缺陷,如果外部硬件长时间断开,
+    /// SerialPort.IsOpen检测不到,并且会无限大占用内存。
+    /// </remarks>
+    /// <param name="state"></param>
+    void CheckDisconnect(Object state)
+    {
+        if (String.IsNullOrEmpty(PortName) || Serial == null || !Serial.IsOpen) return;
 
-            // 如果端口已经不存在,则断开吧
-            if (!SerialPort.GetPortNames().Contains(PortName))
-            {
-                WriteLog("串口{0}已经不存在,准备关闭!", PortName);
+        // 如果端口已经不存在,则断开吧
+        if (!SerialPort.GetPortNames().Contains(PortName))
+        {
+            WriteLog("串口{0}已经不存在,准备关闭!", PortName);
 
-                //OnDisconnect();
-                Close();
-            }
+            //OnDisconnect();
+            Close();
         }
-        #endregion
+    }
+    #endregion
 
-        #region 辅助
-        /// <summary>获取带有描述的串口名,没有时返回空数组</summary>
-        /// <returns></returns>
-        public static String[] GetPortNames()
+    #region 辅助
+    /// <summary>获取带有描述的串口名,没有时返回空数组</summary>
+    /// <returns></returns>
+    public static String[] GetPortNames()
+    {
+        var list = new List<String>();
+        foreach (var item in GetNames())
         {
-            var list = new List<String>();
-            foreach (var item in GetNames())
-            {
-                list.Add(String.Format("{0}({1})", item.Key, item.Value));
-            }
-            return list.ToArray();
+            list.Add(String.Format("{0}({1})", item.Key, item.Value));
         }
+        return list.ToArray();
+    }
 
-        /// <summary>获取串口列表,名称和描述</summary>
-        /// <returns></returns>
-        public static Dictionary<String, String> GetNames()
-        {
-            var dic = new Dictionary<String, String>(StringComparer.OrdinalIgnoreCase);
+    /// <summary>获取串口列表,名称和描述</summary>
+    /// <returns></returns>
+    public static Dictionary<String, String> GetNames()
+    {
+        var dic = new Dictionary<String, String>(StringComparer.OrdinalIgnoreCase);
 #if NC30
-            foreach (var item in SerialPort.GetPortNames())
-            {
-                dic.Add(item, "");
-            }
+        foreach (var item in SerialPort.GetPortNames())
+        {
+            dic.Add(item, "");
+        }
 #else
-            using (var key = Registry.LocalMachine.OpenSubKey(@"HARDWARE\DEVICEMAP\SERIALCOMM", false))
-            using (var usb = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Enum\USB", false))
+        using (var key = Registry.LocalMachine.OpenSubKey(@"HARDWARE\DEVICEMAP\SERIALCOMM", false))
+        using (var usb = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Enum\USB", false))
+        {
+            if (key != null)
             {
-                if (key != null)
+                foreach (var item in key.GetValueNames())
                 {
-                    foreach (var item in key.GetValueNames())
-                    {
-                        var name = key.GetValue(item) + "";
-                        var des = "";
+                    var name = key.GetValue(item) + "";
+                    var des = "";
 
-                        // 尝试枚举USB串口
-                        foreach (var vid in usb.GetSubKeyNames())
+                    // 尝试枚举USB串口
+                    foreach (var vid in usb.GetSubKeyNames())
+                    {
+                        var usbvid = usb.OpenSubKey(vid);
+                        foreach (var elm in usbvid.GetSubKeyNames())
                         {
-                            var usbvid = usb.OpenSubKey(vid);
-                            foreach (var elm in usbvid.GetSubKeyNames())
+                            var sub = usbvid.OpenSubKey(elm);
+                            //if (sub.GetValue("Class") + "" == "Ports")
                             {
-                                var sub = usbvid.OpenSubKey(elm);
-                                //if (sub.GetValue("Class") + "" == "Ports")
+                                var FriendlyName = sub.GetValue("FriendlyName") + "";
+                                if (FriendlyName.Contains("({0})".F(name)))
                                 {
-                                    var FriendlyName = sub.GetValue("FriendlyName") + "";
-                                    if (FriendlyName.Contains("({0})".F(name)))
-                                    {
-                                        des = FriendlyName.TrimEnd("({0})".F(name)).Trim();
-                                        break;
-                                    }
+                                    des = FriendlyName.TrimEnd("({0})".F(name)).Trim();
+                                    break;
                                 }
                             }
-                            if (!des.IsNullOrEmpty()) break;
-                        }
-
-                        // 最后选择设备映射的串口名
-                        if (des.IsNullOrEmpty())
-                        {
-                            des = item;
-                            var p = item.LastIndexOf('\\');
-                            if (p >= 0) des = des.Substring(p + 1);
                         }
+                        if (!des.IsNullOrEmpty()) break;
+                    }
 
-                        //dic.Add(name, des);
-                        // 某台机器上发现,串口有重复
-                        dic[name] = des;
+                    // 最后选择设备映射的串口名
+                    if (des.IsNullOrEmpty())
+                    {
+                        des = item;
+                        var p = item.LastIndexOf('\\');
+                        if (p >= 0) des = des.Substring(p + 1);
                     }
+
+                    //dic.Add(name, des);
+                    // 某台机器上发现,串口有重复
+                    dic[name] = des;
                 }
             }
+        }
 #endif
 
-            return dic;
-        }
+        return dic;
+    }
 
-        /// <summary>从串口列表选择串口,支持自动选择关键字</summary>
-        /// <param name="keyWord">串口名称或者描述符的关键字</param>
-        /// <returns></returns>
-        public static SerialTransport Choose(String keyWord = null)
+    /// <summary>从串口列表选择串口,支持自动选择关键字</summary>
+    /// <param name="keyWord">串口名称或者描述符的关键字</param>
+    /// <returns></returns>
+    public static SerialTransport Choose(String keyWord = null)
+    {
+        var ns = GetNames();
+        if (ns.Count == 0)
         {
-            var ns = GetNames();
-            if (ns.Count == 0)
-            {
-                Console.WriteLine("没有可用串口!");
-                return null;
-            }
-
-            var name = "";
-            var des = "";
+            Console.WriteLine("没有可用串口!");
+            return null;
+        }
 
-            Console.WriteLine("可用串口:");
-            Console.ForegroundColor = ConsoleColor.Green;
-            foreach (var item in ns)
-            {
-                if (item.Value == "Serial0") continue;
+        var name = "";
+        var des = "";
 
-                if (keyWord != null && (item.Key.EqualIgnoreCase(keyWord) || item.Value.Contains(keyWord)))
-                {
-                    name = item.Key;
-                    des = item.Value;
-                }
+        Console.WriteLine("可用串口:");
+        Console.ForegroundColor = ConsoleColor.Green;
+        foreach (var item in ns)
+        {
+            if (item.Value == "Serial0") continue;
 
-                //Console.WriteLine(item);
-                Console.WriteLine("{0,5}({1})", item.Key, item.Value);
-            }
-            // 没有自动选择,则默认最后一个
-            if (name.IsNullOrEmpty())
+            if (keyWord != null && (item.Key.EqualIgnoreCase(keyWord) || item.Value.Contains(keyWord)))
             {
-                var item = ns.Last();
                 name = item.Key;
                 des = item.Value;
             }
-            while (true)
-            {
-                Console.ResetColor();
-                Console.Write("请输入串口名称(默认 ");
-                Console.ForegroundColor = ConsoleColor.Red;
-                Console.Write("{0}", name);
-                Console.ResetColor();
-                Console.Write("):");
-
-                var str = Console.ReadLine();
-                if (str.IsNullOrEmpty()) break;
-
-                // 只有输入有效串口名称才行
-                if (ns.ContainsKey(str))
-                {
-                    name = str;
-                    des = ns[str];
-                    break;
-                }
-            }
-
-            Console.WriteLine();
-            Console.Write("正在打开串口 ");
-            Console.ForegroundColor = ConsoleColor.Green;
-            Console.WriteLine("{0}({1})", name, des);
 
+            //Console.WriteLine(item);
+            Console.WriteLine("{0,5}({1})", item.Key, item.Value);
+        }
+        // 没有自动选择,则默认最后一个
+        if (name.IsNullOrEmpty())
+        {
+            var item = ns.Last();
+            name = item.Key;
+            des = item.Value;
+        }
+        while (true)
+        {
+            Console.ResetColor();
+            Console.Write("请输入串口名称(默认 ");
+            Console.ForegroundColor = ConsoleColor.Red;
+            Console.Write("{0}", name);
             Console.ResetColor();
+            Console.Write("):");
 
-            var sp = new SerialTransport
-            {
-                PortName = name
-            };
+            var str = Console.ReadLine();
+            if (str.IsNullOrEmpty()) break;
 
-            return sp;
+            // 只有输入有效串口名称才行
+            if (ns.ContainsKey(str))
+            {
+                name = str;
+                des = ns[str];
+                break;
+            }
         }
-        #endregion
 
-        #region 日志
-        /// <summary>日志对象</summary>
-        public ILog Log { get; set; } = Logger.Null;
+        Console.WriteLine();
+        Console.Write("正在打开串口 ");
+        Console.ForegroundColor = ConsoleColor.Green;
+        Console.WriteLine("{0}({1})", name, des);
 
-        /// <summary>输出日志</summary>
-        /// <param name="format"></param>
-        /// <param name="args"></param>
-        public void WriteLog(String format, params Object[] args)
-        {
-            if (Log != null && Log.Enable) Log.Info(format, args);
-        }
+        Console.ResetColor();
 
-        /// <summary>已重载</summary>
-        /// <returns></returns>
-        public override String ToString()
+        var sp = new SerialTransport
         {
-            if (!String.IsNullOrEmpty(PortName))
-                return PortName;
-            else
-                return "(SerialPort)";
-        }
+            PortName = name
+        };
+
+        return sp;
+    }
+    #endregion
 
+    #region 日志
+    /// <summary>日志对象</summary>
+    public ILog Log { get; set; } = Logger.Null;
 
-        #endregion
+    /// <summary>输出日志</summary>
+    /// <param name="format"></param>
+    /// <param name="args"></param>
+    public void WriteLog(String format, params Object[] args)
+    {
+        if (Log != null && Log.Enable) Log.Info(format, args);
     }
+
+    /// <summary>已重载</summary>
+    /// <returns></returns>
+    public override String ToString()
+    {
+        if (!String.IsNullOrEmpty(PortName))
+            return PortName;
+        else
+            return "(SerialPort)";
+    }
+
+
+    #endregion
 }
\ No newline at end of file
Modified +17 -18
diff --git a/XCoder/XNet/BenchHelper.cs b/XCoder/XNet/BenchHelper.cs
index 51bbda4..0ede2cb 100644
--- a/XCoder/XNet/BenchHelper.cs
+++ b/XCoder/XNet/BenchHelper.cs
@@ -10,29 +10,28 @@ using NewLife.Threading;
 using TaskEx = System.Threading.Tasks.Task;
 #endif
 
-namespace XCoder.XNet
+namespace XCoder.XNet;
+
+static class BenchHelper
 {
-    static class BenchHelper
+    /// <summary>异步多次发送数据</summary>
+    /// <param name="session">会话</param>
+    /// <param name="pk">数据包</param>
+    /// <param name="times">次数</param>
+    /// <param name="msInterval">间隔</param>
+    /// <returns></returns>
+    public static Task SendConcurrency(this ISocketRemote session, IPacket pk, Int32 times, Int32 msInterval)
     {
-        /// <summary>异步多次发送数据</summary>
-        /// <param name="session">会话</param>
-        /// <param name="pk">数据包</param>
-        /// <param name="times">次数</param>
-        /// <param name="msInterval">间隔</param>
-        /// <returns></returns>
-        public static Task SendConcurrency(this ISocketRemote session, Packet pk, Int32 times, Int32 msInterval)
+        var task = TaskEx.Run(async () =>
         {
-            var task = TaskEx.Run(async () =>
+            for (var i = 0; i < times; i++)
             {
-                for (var i = 0; i < times; i++)
-                {
-                    session.Send(pk);
+                session.Send(pk);
 
-                    await TaskEx.Delay(msInterval);
-                }
-            });
+                await TaskEx.Delay(msInterval);
+            }
+        });
 
-            return task;
-        }
+        return task;
     }
 }
\ No newline at end of file
Modified +2 -2
diff --git a/XCoder/XNet/FrmMain.cs b/XCoder/XNet/FrmMain.cs
index 8987b24..28718bb 100644
--- a/XCoder/XNet/FrmMain.cs
+++ b/XCoder/XNet/FrmMain.cs
@@ -377,7 +377,7 @@ namespace XNet
             // 处理换行
             str = str.Replace("\n", "\r\n");
             var buf = cfg.HexSend ? str.ToHex() : str.GetBytes();
-            var pk = new Packet(buf);
+            var pk = new ArrayPacket(buf);
 
             if (_Client != null)
             {
@@ -418,7 +418,7 @@ namespace XNet
                     for (var i = 0; i < count && _Server != null; i++)
                     {
                         var sw = Stopwatch.StartNew();
-                        var cs = await _Server.SendAllAsync(buf);
+                        var cs = await _Server.SendAllAsync(pk);
                         sw.Stop();
                         BizLog.Info("{3}/{4} 已向[{0}]个客户端发送[{1}]数据 {2:n0}ms", cs, buf.Length, sw.ElapsedMilliseconds, i + 1, count);
                         if (sleep > 0) await TaskEx.Delay(sleep);
Modified +1 -0
diff --git a/XCoder/XNet/FrmMqtt.cs b/XCoder/XNet/FrmMqtt.cs
index bdf2038..7cbc9c1 100644
--- a/XCoder/XNet/FrmMqtt.cs
+++ b/XCoder/XNet/FrmMqtt.cs
@@ -3,6 +3,7 @@ using System.ComponentModel;
 using System.Threading.Tasks;
 using System.Windows.Forms;
 using NewLife;
+using NewLife.Data;
 using NewLife.Log;
 using NewLife.MQTT;
 using NewLife.MQTT.Messaging;
Modified +1 -1
diff --git a/XCoderLinux/SharpApp.cs b/XCoderLinux/SharpApp.cs
index 27c240b..bbddba5 100644
--- a/XCoderLinux/SharpApp.cs
+++ b/XCoderLinux/SharpApp.cs
@@ -63,7 +63,7 @@ namespace XCoder
 
             var asm = AssemblyX.Create(Assembly.GetExecutingAssembly());
             if (set.Title.IsNullOrEmpty()) set.Title = asm.Title;
-            _title = Title = String.Format("{2} v{0} {1:HH:mm:ss}", asm.CompileVersion, asm.Compile, set.Title);
+            _title = Title = String.Format("{2} v{0} {1:HH:mm:ss}", asm.FileVersion, asm.Compile, set.Title);
 
             _load.ContinueWith(t => LoadForms(t.Result));
 
Modified +1 -0
diff --git a/XCoderLinux/Util/ControlHelper.cs b/XCoderLinux/Util/ControlHelper.cs
index 75668cd..508ae01 100644
--- a/XCoderLinux/Util/ControlHelper.cs
+++ b/XCoderLinux/Util/ControlHelper.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using Gtk;
+using NewLife;
 
 namespace XCoder.Util
 {
Modified +7 -4
diff --git a/XCoderLinux/XCoderLinux.csproj b/XCoderLinux/XCoderLinux.csproj
index 8893159..e3ebb46 100644
--- a/XCoderLinux/XCoderLinux.csproj
+++ b/XCoderLinux/XCoderLinux.csproj
@@ -2,7 +2,7 @@
 
   <PropertyGroup>
     <OutputType>Exe</OutputType>
-    <TargetFrameworks>net5.0;netcoreapp3.1</TargetFrameworks>
+    <TargetFrameworks>net8.0</TargetFrameworks>
     <AssemblyName>XCoder</AssemblyName>
     <RootNamespace>XCoder</RootNamespace>
     <AssemblyTitle>新生命码神工具</AssemblyTitle>
@@ -14,7 +14,9 @@
     <AssemblyVersion>8.0.*</AssemblyVersion>
     <Deterministic>false</Deterministic>
     <ApplicationIcon>..\XCoder\leaf.ico</ApplicationIcon>
-    <OutputPath>..\..\XCoderLinux\</OutputPath>
+    <OutputPath>..\Bin\XCoderLinux\</OutputPath>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <LangVersion>latest</LangVersion>
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <DefineConstants>TRACE;NC30;__CORE__</DefineConstants>
@@ -48,8 +50,9 @@
 
   <ItemGroup>
     <PackageReference Include="GtkSharp" Version="3.24.24.34" />
-    <PackageReference Include="NewLife.Core" Version="10.10.2024.803" />
-    <PackageReference Include="NewLife.XCode" Version="11.15.2024.806" />
+    <PackageReference Include="NewLife.Core" Version="11.5.2025.501" />
+    <PackageReference Include="NewLife.Stardust" Version="3.3.2025.506" />
+    <PackageReference Include="NewLife.XCode" Version="11.19.2025.501" />
     <PackageReference Include="System.IO.Ports" Version="6.0.0" />
     <PackageReference Include="System.Management" Version="6.0.0" />
   </ItemGroup>
Modified +2 -1
diff --git a/XCoderLinux/XCom/SerialPortList.cs b/XCoderLinux/XCom/SerialPortList.cs
index c24b074..e742e15 100644
--- a/XCoderLinux/XCom/SerialPortList.cs
+++ b/XCoderLinux/XCom/SerialPortList.cs
@@ -7,6 +7,7 @@ using System.IO.Ports;
 using System.Linq;
 using System.Text;
 using Gtk;
+using NewLife.Data;
 using NewLife.Log;
 using NewLife.Net;
 using NewLife.Threading;
@@ -451,7 +452,7 @@ namespace NewLife.Windows
         StreamReader _reader;
         void OnReceived(Object sender, ReceivedEventArgs e)
         {
-            var data = e.Packet.ReadBytes();
+            var data = e.Packet.ReadBytes(0, -1);
             if (data == null || data.Length < 1) return;
 
             BytesOfReceived += data.Length;
Modified +1 -1
diff --git a/XCoderLinux/XNet/FrmMain.cs b/XCoderLinux/XNet/FrmMain.cs
index 77b69f3..9c879dc 100644
--- a/XCoderLinux/XNet/FrmMain.cs
+++ b/XCoderLinux/XNet/FrmMain.cs
@@ -426,7 +426,7 @@ namespace XNet
                     for (var i = 0; i < count && _Server != null; i++)
                     {
                         var sw = Stopwatch.StartNew();
-                        var cs = await _Server.SendAllAsync(buf);
+                        var cs = await _Server.SendAllAsync(pk);
                         sw.Stop();
                         BizLog.Info("{3}/{4} 已向[{0}]个客户端发送[{1}]数据 {2:n0}ms", cs, buf.Length, sw.ElapsedMilliseconds, i + 1, count);
                         if (sleep > 0) await TaskEx.Delay(sleep);
Modified +1 -1
diff --git a/XCoderWpf/XCoderWpf.csproj b/XCoderWpf/XCoderWpf.csproj
index bf963b4..be04b10 100644
--- a/XCoderWpf/XCoderWpf.csproj
+++ b/XCoderWpf/XCoderWpf.csproj
@@ -31,7 +31,7 @@
   <ItemGroup>
     <PackageReference Include="HandyControls" Version="3.3.9" />
     <PackageReference Include="Microsoft.Data.SqlClient" Version="4.0.0" />
-    <PackageReference Include="NewLife.XCode" Version="11.15.2024.806" />
+    <PackageReference Include="NewLife.XCode" Version="11.19.2025.501" />
     <PackageReference Include="Prism.DryIoc" Version="8.1.97" />
   </ItemGroup>
 
Modified +2 -28
diff --git "a/\347\240\201\347\245\236\345\267\245\345\205\267.sln" "b/\347\240\201\347\245\236\345\267\245\345\205\267.sln"
index 2ef2e56..b65083c 100644
--- "a/\347\240\201\347\245\236\345\267\245\345\205\267.sln"
+++ "b/\347\240\201\347\245\236\345\267\245\345\205\267.sln"
@@ -1,7 +1,7 @@
 
 Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.29318.209
+# Visual Studio Version 17
+VisualStudioVersion = 17.14.36109.1
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Others", "Others", "{32891F65-FBA1-42B2-918E-61F3A9623F2A}"
 	ProjectSection(SolutionItems) = preProject
@@ -18,8 +18,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CrazyCoder", "CrazyCoder\Cr
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XCoderWpf", "XCoderWpf\XCoderWpf.csproj", "{405D4D22-FF61-4796-A3F2-222CFDA326D2}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XCoder40", "XCoder40\XCoder40.csproj", "{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}"
-EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -132,30 +130,6 @@ Global
 		{405D4D22-FF61-4796-A3F2-222CFDA326D2}.Release|x64.Build.0 = Release|Any CPU
 		{405D4D22-FF61-4796-A3F2-222CFDA326D2}.Release|x86.ActiveCfg = Release|Any CPU
 		{405D4D22-FF61-4796-A3F2-222CFDA326D2}.Release|x86.Build.0 = Release|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Debug|ARM.ActiveCfg = Debug|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Debug|ARM.Build.0 = Debug|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Debug|iPhone.ActiveCfg = Debug|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Debug|iPhone.Build.0 = Debug|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Debug|x64.Build.0 = Debug|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Debug|x86.Build.0 = Debug|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Release|Any CPU.Build.0 = Release|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Release|ARM.ActiveCfg = Release|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Release|ARM.Build.0 = Release|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Release|iPhone.ActiveCfg = Release|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Release|iPhone.Build.0 = Release|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Release|x64.ActiveCfg = Release|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Release|x64.Build.0 = Release|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Release|x86.ActiveCfg = Release|Any CPU
-		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Release|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE