@@ -47,6 +47,27 @@ public FakeServerMultiCaster(
4747 }
4848
4949 public event Action < string , int > ? OnListenedLanServer ;
50+
51+ private static IPAddress GetLocalIpAddress ( )
52+ {
53+ var networkInterfaces = System . Net . NetworkInformation . NetworkInterface . GetAllNetworkInterfaces ( )
54+ . Where ( ni => ni . OperationalStatus == System . Net . NetworkInformation . OperationalStatus . Up
55+ && ni . NetworkInterfaceType != System . Net . NetworkInformation . NetworkInterfaceType . Loopback ) ;
56+
57+ foreach ( var ni in networkInterfaces )
58+ {
59+ var ipProps = ni . GetIPProperties ( ) ;
60+ foreach ( var addr in ipProps . UnicastAddresses )
61+ {
62+ if ( addr . Address . AddressFamily == AddressFamily . InterNetwork )
63+ {
64+ return addr . Address ;
65+ }
66+ }
67+ }
68+
69+ throw new Exception ( "No network adapters with an IPv4 address in the system!" ) ;
70+ }
5071
5172 private void OnReceiveMcMulticastMessage ( McMulticastMessage message , PacketContext context )
5273 {
@@ -59,19 +80,39 @@ private void OnReceiveMcMulticastMessage(McMulticastMessage message, PacketConte
5980 return ;
6081 }
6182
62- var multicastSocket = new Socket ( SocketType . Dgram , ProtocolType . Udp ) ;
63- var multicastOption = new MulticastOption ( MulticastAddress , IPAddress . Any ) ;
83+ Socket ? socket = null ;
84+
85+ if ( OperatingSystem . IsWindows ( ) )
86+ {
87+ socket = new Socket ( SocketType . Dgram , ProtocolType . Udp ) ;
88+
89+ var multicastOption = new MulticastOption ( MulticastAddress , IPAddress . Any ) ;
90+ socket . SetSocketOption ( SocketOptionLevel . IP , SocketOptionName . AddMembership , multicastOption ) ;
91+ }
92+
93+ if ( OperatingSystem . IsMacOS ( ) || OperatingSystem . IsLinux ( ) )
94+ {
95+ socket = new Socket ( AddressFamily . InterNetwork , SocketType . Dgram , ProtocolType . Udp ) ;
96+
97+ var localIp = GetLocalIpAddress ( ) ;
98+
99+ socket . SetSocketOption ( SocketOptionLevel . IP , SocketOptionName . MulticastInterface , localIp . GetAddressBytes ( ) ) ;
100+ socket . SetSocketOption ( SocketOptionLevel . IP , SocketOptionName . MulticastTimeToLive , 255 ) ;
101+ socket . Bind ( new IPEndPoint ( localIp , 0 ) ) ;
102+ }
103+
104+ ArgumentNullException . ThrowIfNull ( socket ) ;
64105
65- multicastSocket . SetSocketOption ( SocketOptionLevel . IP , SocketOptionName . AddMembership , multicastOption ) ;
106+ using var multicastSocket = socket ;
66107
67- //传递给客户端的是另一个端口,并非源端口。客户端连接此端口通过P2P.NET和源端口通信
68108 var mess = $ "[MOTD]{ message . Name } [/MOTD][AD]{ proxy . LocalMappingPort } [/AD]";
69109 var buf = Encoding . Default . GetBytes ( mess ) ;
70110
71111 multicastSocket . SendTo ( buf , MulticastIpe ) ;
72112 _logger . LogMulticastMessageToClient ( proxy . LocalMappingPort , message . Name ) ;
73113 }
74114
115+
75116 private void ListenedLanServer ( string serverName , ushort port )
76117 {
77118 _logger . LogLanServerIsListened ( serverName , port ) ;
@@ -120,37 +161,50 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
120161 {
121162 if ( _roomInfoManager . CurrentGroupInfo == null )
122163 {
123- // We are not in a room, so we don't need to listen to multicast
124164 await Task . Delay ( 3000 , stoppingToken ) ;
125165 continue ;
126166 }
127167
128- using var multicastSocket = new Socket ( SocketType . Dgram , ProtocolType . Udp ) ;
129- var multicastOption = new MulticastOption ( MulticastAddress , IPAddress . Any ) ;
130-
131- multicastSocket . SetSocketOption (
132- SocketOptionLevel . IP ,
133- SocketOptionName . AddMembership ,
134- multicastOption ) ;
168+ using var multicastSocket = new Socket ( AddressFamily . InterNetwork , SocketType . Dgram , ProtocolType . Udp ) ;
135169
136- multicastSocket . SetSocketOption (
137- SocketOptionLevel . Socket ,
138- SocketOptionName . ReuseAddress ,
139- true ) ;
170+ // Allow multiple sockets to bind to same address (important for Linux/macOS)
171+ multicastSocket . SetSocketOption ( SocketOptionLevel . Socket , SocketOptionName . ReuseAddress , true ) ;
140172
173+ // Bind to ANY address but the multicast port
141174 multicastSocket . Bind ( new IPEndPoint ( IPAddress . Any , MulticastPort ) ) ;
142-
143- var receiveFromResult = await multicastSocket . ReceiveFromAsync ( buffer , MulticastIpe ) ;
144- var message = Encoding . UTF8 . GetString ( buffer , 0 , receiveFromResult . ReceivedBytes ) ;
145- var serverName = message [ "[MOTD]" . Length ..message . IndexOf ( "[/MOTD]" , StringComparison . Ordinal ) ] ;
146- var portStart = message . IndexOf ( "[AD]" , StringComparison . Ordinal ) + 4 ;
147- var portEnd = message . IndexOf ( "[/AD]" , StringComparison . Ordinal ) ;
148- var port = ushort . Parse ( message [ portStart ..portEnd ] ) ;
149175
150- if ( ! serverName . StartsWith ( $ "[{ Prefix } ]") ) //如果[ConnectX]开头,则是自己发出的,忽略
151- ListenedLanServer ( serverName , port ) ;
176+ // Join multicast group
177+ var multicastOption = new MulticastOption ( MulticastAddress , IPAddress . Any ) ;
178+ multicastSocket . SetSocketOption ( SocketOptionLevel . IP , SocketOptionName . AddMembership , multicastOption ) ;
152179
153- multicastSocket . Close ( ) ;
180+ try
181+ {
182+ var receiveFromResult = await multicastSocket . ReceiveFromAsync ( buffer , SocketFlags . None ,
183+ new IPEndPoint ( IPAddress . Any , 0 ) , stoppingToken ) ;
184+ var message = Encoding . UTF8 . GetString ( buffer , 0 , receiveFromResult . ReceivedBytes ) ;
185+
186+ var serverName = message [ "[MOTD]" . Length ..message . IndexOf ( "[/MOTD]" , StringComparison . Ordinal ) ] ;
187+ var portStart = message . IndexOf ( "[AD]" , StringComparison . Ordinal ) + 4 ;
188+ var portEnd = message . IndexOf ( "[/AD]" , StringComparison . Ordinal ) ;
189+ var port = ushort . Parse ( message [ portStart ..portEnd ] ) ;
190+
191+ if ( ! serverName . StartsWith ( $ "[{ Prefix } ]") )
192+ {
193+ ListenedLanServer ( serverName , port ) ;
194+ }
195+ }
196+ catch ( SocketException ex ) when ( ex . SocketErrorCode == SocketError . Interrupted )
197+ {
198+ // Expected during shutdown
199+ }
200+ catch ( Exception ex )
201+ {
202+ _logger . LogError ( ex , "Error receiving multicast message" ) ;
203+ }
204+ finally
205+ {
206+ multicastSocket . Close ( ) ;
207+ }
154208
155209 await Task . Delay ( 3000 , stoppingToken ) ;
156210 }
0 commit comments