NewLife/X

[fix]修正UdpServer在接收广播时连续启动接收的错误,在StarAgent中,此时可能收到广播包,SocketFlags是Broadcast,需要清空,否则报错“参考的对象类型不支持尝试的操作”;
无需设置SocketOptionName.PacketInformation,在ReceiveMessageFromAsync时会自动设置,并且支持ipv6;
石头 编写于 2024-10-10 00:36:00 石头 提交于 2024-10-10 00:45:43
共计: 修改3个文件,增加12行、删除10行。
修改 +4 -0
修改 +6 -1
修改 +2 -9
修改 +4 -0
diff --git a/NewLife.Core/Net/NetUri.cs b/NewLife.Core/Net/NetUri.cs
index 0e4e612..e1c388e 100644
--- a/NewLife.Core/Net/NetUri.cs
+++ b/NewLife.Core/Net/NetUri.cs
@@ -213,6 +213,10 @@ public class NetUri
     /// <summary>获取该域名下所有IP节点(含端口)</summary>
     /// <returns></returns>
     public IPEndPoint[] GetEndPoints() => GetAddresses().Select(e => new IPEndPoint(e, Port)).ToArray();
+
+    /// <summary>克隆</summary>
+    /// <returns></returns>
+    public NetUri Clone() => new() { Type = Type, Host = Host, Port = Port, Address = Address };
     #endregion
 
     #region 辅助
修改 +6 -1
diff --git a/NewLife.Core/Net/UdpServer.cs b/NewLife.Core/Net/UdpServer.cs
index 338f886..c3a5962 100644
--- a/NewLife.Core/Net/UdpServer.cs
+++ b/NewLife.Core/Net/UdpServer.cs
@@ -85,7 +85,9 @@ public class UdpServer : SessionBase, ISocketServer, ILogFeature
                 // 启用地址重用后,即使旧进程未退出,新进程也可以监听,但只有旧进程退出后,新进程才能接受对该端口的连接请求
                 if (ReuseAddress) sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
 
-                sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.PacketInformation, true);
+                // 无需设置SocketOptionName.PacketInformation,在ReceiveMessageFromAsync时会自动设置
+                //if (sock.AddressFamily == AddressFamily.InterNetwork)
+                //    sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.PacketInformation, true);
             }
             catch (Exception ex)
             {
@@ -218,6 +220,9 @@ public class UdpServer : SessionBase, ISocketServer, ILogFeature
         // 每次接收以后,这个会被设置为远程地址,这里重置一下,以防万一
         se.RemoteEndPoint = new IPEndPoint(IPAddress.Any.GetRightAny(Local.EndPoint.AddressFamily), 0);
 
+        // 在StarAgent中,此时可能收到广播包,SocketFlags是Broadcast,需要清空,否则报错“参考的对象类型不支持尝试的操作”
+        se.SocketFlags = SocketFlags.None;
+
         //return Client.ReceiveFromAsync(se);
         return Client.ReceiveMessageFromAsync(se);
     }
修改 +2 -9
diff --git a/NewLife.Core/Net/UdpSession.cs b/NewLife.Core/Net/UdpSession.cs
index 40644a7..73525a3 100644
--- a/NewLife.Core/Net/UdpSession.cs
+++ b/NewLife.Core/Net/UdpSession.cs
@@ -23,16 +23,8 @@ public class UdpSession : DisposeBase, ISocketSession, ITransport, ILogFeature
     /// <summary>底层Socket</summary>
     Socket? ISocket.Client => Server?.Client;
 
-    ///// <summary>数据流</summary>
-    //public Stream Stream { get; set; }
-
-    private NetUri? _Local;
     /// <summary>本地地址</summary>
-    public NetUri Local
-    {
-        get => _Local ??= Server.Local;
-        set => Server.Local = _Local = value;
-    }
+    public NetUri Local { get; set; }
 
     /// <summary>端口</summary>
     public Int32 Port { get => Local.Port; set => Local.Port = value; }
@@ -83,6 +75,7 @@ public class UdpSession : DisposeBase, ISocketSession, ITransport, ILogFeature
         Remote = new NetUri(NetType.Udp, remote);
         Tracer = server.Tracer;
 
+        Local = server.Local.Clone();
         if (local != null) Local.Address = local;
 
         // 检查并开启广播