using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using SuperSocket.Common; using SuperSocket.SocketBase; using SuperSocket.SocketBase.Config; namespace SuperSocket.SocketEngine { class UdpSocketListener : SocketListenerBase { private Socket m_ListenSocket; private SocketAsyncEventArgs m_ReceiveSAE; public UdpSocketListener(ListenerInfo info) : base(info) { } /// /// Starts to listen /// /// The server config. /// public override bool Start(IServerConfig config) { try { m_ListenSocket = new Socket(this.EndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp); m_ListenSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); m_ListenSocket.Bind(this.EndPoint); //Mono doesn't support it if (Platform.SupportSocketIOControlByCodeEnum) { uint IOC_IN = 0x80000000; uint IOC_VENDOR = 0x18000000; uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12; byte[] optionInValue = { Convert.ToByte(false) }; byte[] optionOutValue = new byte[4]; m_ListenSocket.IOControl((int)SIO_UDP_CONNRESET, optionInValue, optionOutValue); } var eventArgs = new SocketAsyncEventArgs(); m_ReceiveSAE = eventArgs; eventArgs.Completed += new EventHandler(eventArgs_Completed); eventArgs.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0); int receiveBufferSize = config.ReceiveBufferSize <= 0 ? 2048 : config.ReceiveBufferSize; var buffer = new byte[receiveBufferSize]; eventArgs.SetBuffer(buffer, 0, buffer.Length); m_ListenSocket.ReceiveFromAsync(eventArgs); return true; } catch (Exception e) { OnError(e); return false; } } void eventArgs_Completed(object sender, SocketAsyncEventArgs e) { if (e.SocketError != SocketError.Success) { var errorCode = (int)e.SocketError; //The listen socket was closed if (errorCode == 995 || errorCode == 10004 || errorCode == 10038) return; OnError(new SocketException(errorCode)); } if (e.LastOperation == SocketAsyncOperation.ReceiveFrom) { try { OnNewClientAcceptedAsync(m_ListenSocket, new object[] { e.Buffer.CloneRange(e.Offset, e.BytesTransferred), e.RemoteEndPoint.Serialize() }); } catch (Exception exc) { OnError(exc); } try { m_ListenSocket.ReceiveFromAsync(e); } catch (Exception exc) { OnError(exc); } } } public override void Stop() { if (m_ListenSocket == null) return; lock(this) { if (m_ListenSocket == null) return; m_ReceiveSAE.Completed -= new EventHandler(eventArgs_Completed); m_ReceiveSAE.Dispose(); m_ReceiveSAE = null; if(!Platform.IsMono) { try { m_ListenSocket.Shutdown(SocketShutdown.Both); } catch { } } try { m_ListenSocket.Close(); } catch { } finally { m_ListenSocket = null; } } OnStopped(); } } }