【正文】
throw new Exception( Unable to get local address )。 } return aryLocalAddr。 } public TcpServer(int nPortListen) { _TcpServer(nPortListen, GetAddresses()[0])。 } public TcpServer(int nPortListen, IPAddress ip) { _TcpServer(nPortListen, ip)。 } 8 // Shut down the listener public void Dispose() { // Shutting down is a real PITA. You can39。t close the listener // while there is an outstanding async call active. And you can39。t // cancel the async call. Grr. As a workaround, this routine // makes a connection to the port. The OnConnect routine, recognizing // that we are in shutdown, doesn39。t create a new async call. TcpClient t = null。 // Only want one thread to be preforming shutdown at a time. lock (this) { // Have we already shutdown? if (!m_bShuttingDown) { m_bShuttingDown = true。 // Disconnect each client foreach (SockWrapper s in m_aryClients) { try { ()。 ()。 } catch {} } m_aryClients = null。 // Connect to the port to trigger the async listener IPEndPoint ep = (IPEndPoint)。 t = new TcpClient((), )。 } } if (t != null) { // Listen for the async listener to let go. This must be done // outside the crit section since the listener needs to lock it. (3000, false)。 lock (this) { 9 // close everything down ()。 m_sockListener = null。 ()。 ()。 ShutDownReady = null。 } } } ~TcpServer() { // If Dispose is not called against our class and the destructor is // called, some of the member variables in this class have already // been disposed. Such being the case, there39。s no way to clean up // nicely. Moral: Always call Dispose. //Dispose()。 } // Send to all connected clients public void SendToAll(MemoryStream m) { _SendToAll((), (int))。 } public void SendToAll(byte [] b) { _SendToAll(b, )。 } public int Connections { get { return 。 } } public event TcpConnected Connected。 public event TcpConnected Disconnected。 public event TcpReceive DataReceived。 public event TcpSend Send。 private void _TcpServer(int nPortListen, IPAddress ip) { try 10 { // Initialize member vars m_aryClients = new ArrayList(5)。 ShutDownReady = new ManualResetEvent(false)。 m_bShuttingDown = false。 // Create the listener socket in this machine39。s IP address m_sockListener = new Socket( , , )。 ( new IPEndPoint( ip, nPortListen ) )。 ( MAXCONNECTIONS )。 // Setup a callback to be notified of connection requests ( new AsyncCallback( OnConnectRequest ), m_sockListener )。 } catch { m_bShuttingDown = true。 throw。 } } private void _SendToAll(byte [] b, int iLength) { lock (this) { if (!m_bShuttingDown) { foreach (SockWrapper s in m_aryClients) { _SendOne(s, b, iLength)。 } } } } private void _SendOne(SockWrapper s, byte [] b, int iLength) { try { bool bSend = true。 if (Send != null) 11 Send(this, ref , ref bSend)。 if (bSend) (b, iLength, )。 } catch { // Ignore the error. If the client is dead, OnReceiveData // will be called to close the connection. I would remove it // anyway, except bad things happen if you remove an entry // from a list while using foreach. } } // Client has connected private void OnConnectRequest( IAsyncResult ar ) { // Get the listener and client Socket listener = (Socket)。 Socket client = ( ar )。 lock (this) { if (!m_bShuttingDown) { // Wrap the client and add it to the array SockWrapper s = new SockWrapper(client)。 ( s )。 // Fire the Connected event if (Connected != null) Connected(this, ref )。 // Set up an async wait for packets from the client AsyncCallback receiveData = new Asy