| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 | using System;using System.Net;using System.Net.Sockets;using System.Threading;namespace Renci.SshNet.Tests.Common{    public class AsyncSocketListener : IDisposable    {        private readonly IPEndPoint _endPoint;        private readonly ManualResetEvent _acceptCallbackDone;        private Socket _listener;        private Thread _receiveThread;        private bool _started;        public delegate void BytesReceivedHandler(byte[] bytesReceived, Socket socket);        public event BytesReceivedHandler BytesReceived;        public AsyncSocketListener(IPEndPoint endPoint)        {            _endPoint = endPoint;            _acceptCallbackDone = new ManualResetEvent(false);        }        public void Start()        {            _listener = new Socket(_endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);            _listener.Bind(_endPoint);            _listener.Listen(1);            _started = true;            _receiveThread = new Thread(StartListener);            _receiveThread.Start(_listener);        }        public void Stop()        {            _started = false;            if (_listener != null)            {                _listener.Dispose();                _listener = null;            }            if (_receiveThread != null)            {                _receiveThread.Join();                _receiveThread = null;            }        }        public void Dispose()        {            Stop();            GC.SuppressFinalize(this);        }        private void StartListener(object state)        {            var listener = (Socket)state;            while (_started)            {                _acceptCallbackDone.Reset();                listener.BeginAccept(AcceptCallback, listener);                _acceptCallbackDone.WaitOne();            }        }        private void AcceptCallback(IAsyncResult ar)        {            // Signal the main thread to continue.            _acceptCallbackDone.Set();            // Get the socket that handles the client request.            var listener = (Socket)ar.AsyncState;            try            {                var handler = listener.EndAccept(ar);                var state = new SocketStateObject(handler);                handler.BeginReceive(state.Buffer, 0, state.Buffer.Length, 0, ReadCallback, state);            }            catch (ObjectDisposedException)            {                // when the socket is closed, an ObjectDisposedException is thrown                // by Socket.EndAccept(IAsyncResult)            }        }        private void ReadCallback(IAsyncResult ar)        {            // Retrieve the state object and the handler socket            // from the asynchronous state object.            var state = (SocketStateObject)ar.AsyncState;            var handler = state.Socket;            // Read data from the client socket.            var bytesRead = handler.EndReceive(ar);            if (bytesRead > 0)            {                var bytesReceived = new byte[bytesRead];                Array.Copy(state.Buffer, bytesReceived, bytesRead);                SignalBytesReceived(bytesReceived, handler);                // prepare to receive more bytes                try                {                    handler.BeginReceive(state.Buffer, 0, state.Buffer.Length, 0, ReadCallback, state);                }                catch (ObjectDisposedException)                {                    // when the socket is closed, an ObjectDisposedException is thrown                }            }        }        private void SignalBytesReceived(byte[] bytesReceived, Socket client)        {            var subscribers = BytesReceived;            if (subscribers != null)                subscribers(bytesReceived, client);        }        private class SocketStateObject        {            public Socket Socket { get; private set; }            public readonly byte[] Buffer = new byte[1024];            public SocketStateObject(Socket handler)            {                Socket = handler;            }        }    }}
 |