如何在Windows应用程序中保持异步system.net.socket监听器的活动

时间:2015-04-18 13:01:54

标签: c# .net multithreading sockets

我正在使用多线程system.net.socket来监听单个端口。我想捕获来自多个客户端的同时请求。这是我的样本:

private static ManualResetEvent _manualResetEvent = new ManualResetEvent(false);

public class Program
{
    static void Main(string[] args)
    {
        Program program = new Program();
        Thread threadListener = new Thread(program.StartListening);
        threadListener.Start();
    }

    private void StartListening()
    {
         IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, Convert.ToInt32(ConfigurationManager.AppSettings["httpPort"].ToString()));

         Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

         listener.Blocking = false;
         listener.Bind(localEndPoint);
         listener.Listen(10);

         listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
    }

    public static void AcceptCallback(IAsyncResult ar)
    {
         _manualResetEvent.Set();

         Socket listener = (Socket)ar.AsyncState;

         Socket handler = listener.EndAccept(ar);

         StateObject state = new StateObject();
         state.workSocket = handler;

         handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);

         listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
    }

    private void ReceiveCallback(IAsyncResult result)
    {
        StateObject state = null;
        Socket handler = null;

        try
        {
            state = (StateObject)result.AsyncState;
            handler = state.workSocket;

            int numBytesReceived = handler.EndReceive(result);

            if (!handler.Connected)
            {
                handler.Close();
                return;
            }

            if (numBytesReceived > 0)
            {
                state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, numBytesReceived));

                string[] lines = state.sb.ToString().Split('\n');

                if (lines[lines.Length-1] == "EOF")
                {
                    // Do something according to client request
                }
                else
                {
                    // We didn't receive all data. Continue receiving...
                    handler.BeginReceive(state.buffer, 0, state.buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
                }
            }
        }
        catch (ObjectDisposedException ex)
        {
            // Don't care
        }
        catch (Exception ex)
        {                
            if (handler != null)
            {
                handler.Close();
            }
        }
    }
}

public class StateObject
{
    public Socket workSocket = null;
    public const int BufferSize = 256;
    public byte[] buffer = new byte[BufferSize];
    public StringBuilder sb = new StringBuilder();
}

问题是我无法仅使用这些代码来运行应用程序。如果我运行此应用程序并捕获客户端请求,我的ReceiveCallBack方法可以正常工作,并且应用程序在成功执行后停止。

我可以使用此MSDN link中的示例代码来保持我的应用程序活跃。它在StartListening方法中使用while循环,如下所示:

while (true) 
{
     allDone.Reset();
     listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
     allDone.WaitOne();
}

但似乎MSDN为阻塞侦听器设计了此代码。我的意思是它不允许同时连接。所以这对我来说不合适。

我必须阻止我的应用程序在执行我的代码后停止而不在MSDN示例中使用while循环。我必须让它继续运行并持续监听多个同时连接。

那么如何让该应用程序继续运行?

由于

1 个答案:

答案 0 :(得分:0)

问题在于没有线程可以让你的进程保持活跃状态​​。在很短的时间内,只有线程池线程在运行并且运行时关闭。

从Main开始一个新线程什么也没做。告诉我你认为这应该实现的目标,我将澄清误解。 Main应该看起来像StartListening(); Thread.Sleep(Timeout.Infinite);。 (反直观!)

除了代码是可行的,虽然质量低。我有太多问题需要详细评论。将此内容提交给Codereview SE。