private void StartListen() { try { // Dispose all old receivers. foreach (var receiver in m_pDataReceivers.ToArray()) { try { receiver.Dispose(); } catch (Exception ex) { OnError(ex); } } m_pDataReceivers.Clear(); // Dispose all old sockets. foreach (var socket in m_pSockets.ToArray()) { try { socket.Dispose(); } catch (Exception ex) { OnError(ex); } } m_pSockets.Clear(); m_pSocketsIPv4.Clear(); m_pSocketsIPv6.Clear(); m_pBindSockets.Clear(); // We must replace IPAddress.Any to all available IPs, otherwise it's impossible to send // reply back to UDP packet sender on same local EP where packet received. // This is very important when clients are behind NAT. var listeningEPs = new List <IPEndPoint>(); foreach (var ep in m_pBindings) { if (ep.Address.Equals(IPAddress.Any)) { // Add localhost. var localEP = new IPEndPoint(IPAddress.Loopback, ep.Port); if (!listeningEPs.Contains(localEP)) { listeningEPs.Add(localEP); } foreach (var ip in NetworkUtil.GetIPAddresses()) { if (ip.AddressFamily == AddressFamily.InterNetwork) { localEP = new IPEndPoint(ip, ep.Port); if (!listeningEPs.Contains(localEP)) { listeningEPs.Add(localEP); } } } } else if (ep.Address.Equals(IPAddress.IPv6Any)) { foreach (var ip in NetworkUtil.GetIPAddresses()) { if (ip.AddressFamily == AddressFamily.InterNetworkV6) { IPEndPoint localEP = new IPEndPoint(ip, ep.Port); if (!listeningEPs.Contains(localEP)) { listeningEPs.Add(localEP); } } } } else { if (!listeningEPs.Contains(ep)) { listeningEPs.Add(ep); } } } // Create sockets. m_pSockets = new List <Socket>(); m_pBindSockets = new Dictionary <string, Socket>(); foreach (var ep in listeningEPs) { try { var socket = NetworkUtil.CreateSocket(ep, ProtocolType.Udp); m_pSockets.Add(socket); if (!ep.Address.Equals(IPAddress.Loopback)) { m_pBindSockets[ep.ToString()] = socket; } // Create UDP data receivers. for (int i = 0; i < m_ReceiversPerSocket; i++) { var receiver = new UDP_DataReceiver(socket, m_MTU); receiver.PacketReceived += (sender, e) => { try { ProcessUdpPacket(e); } catch (Exception ex) { OnError(ex); } }; receiver.Error += (sender, e) => { OnError(e.Exception); }; m_pDataReceivers.Add(receiver); receiver.Start(); } } catch (Exception ex) { OnError(ex); } } // Create round-robin send sockets. // NOTE: We must skip localhost, it can't be used for sending out of server. m_pSocketsIPv4 = new CycleCollection <Socket>(); m_pSocketsIPv6 = new CycleCollection <Socket>(); foreach (Socket socket in m_pSockets) { if (((IPEndPoint)socket.LocalEndPoint).AddressFamily == AddressFamily.InterNetwork) { if (!((IPEndPoint)socket.LocalEndPoint).Address.Equals(IPAddress.Loopback)) { m_pSocketsIPv4.Add(socket); } } else if (((IPEndPoint)socket.LocalEndPoint).AddressFamily == AddressFamily.InterNetworkV6) { m_pSocketsIPv6.Add(socket); } } if (m_pBindSelector != null) { m_pBindSelector.Load(m_pBindSockets.Keys.ToArray()); } } catch (Exception ex) { OnError(ex); } }