我可以启动多个TcpListener BeginAcceptTcpClient异步操作

时间:2016-02-11 09:39:17

标签: c# asynchronous tcpclient tcplistener

启动许多异步操作可能会出现问题吗?

我正在编写TCP服务器,其中并发客户端的数量是上限。我想出了服务器包含一定数量的插槽的想法。每个插槽在共享BeginAcceptTcpClient实例上启动异步TcpListener调用。当客户端连接时,第一个可用的异步操作将通过回调返回。然后,我可以再次调用TcpClient来处理BeginAcceptTcpClient实例和可重新插入的插槽。使用这种架构,我不必手动关心同步计数器来限制客户端连接。 Incomming连接等待重新插入插槽。但我不确定这是不是一个好主意。

示例控制台程序:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace SlotTcpServerSample
{
    internal class Program
    {
        private class Slot : IDisposable
        {
            private TcpListener _listener;
            private EventWaitHandle _closed;

            public Slot(TcpListener listener)
            {
                _listener = listener;
                _closed = new ManualResetEvent(false);
            }

            public void Open(AsyncCallback callback)
            {
                _listener.BeginAcceptTcpClient(callback, this);
            }

            public void Close()
            {
                _closed.Set();
            }

            public void WaitForClose()
            {
                _closed.WaitOne();
            }

            public void Dispose()
            {
                _closed.Close();
            }
        }

        private class TcpServer
        {
            private const int MAX = 10;

            private object _sync;
            private Slot[] _slots;
            private IPEndPoint _endpoint;
            private TcpListener _listener;

            public TcpServer(IPEndPoint endpoint)
            {
                _sync = new object();
                _endpoint = endpoint;
            }

            public void Start()
            {
                lock (_sync)
                {
                    if (_listener != null)
                        return;

                    _listener = new TcpListener(_endpoint);

                    _slots = new Slot[MAX];
                    for (int i = 0; i < MAX; i++)
                        _slots[i] = new Slot(_listener);

                    _listener.Start();

                    foreach (Slot slot in _slots)
                        slot.Open(HandleConnection);
                }
            }

            public void Stop()
            {
                lock (_sync)
                {
                    if (_listener == null)
                        return;

                    _listener.Stop();

                    foreach (Slot slot in _slots)
                    {
                        slot.WaitForClose();
                        slot.Dispose();
                    }

                    _listener = null;
                }
            }

            private void HandleConnection(IAsyncResult asyncResult)
            {
                Slot slot = (Slot)asyncResult.AsyncState;

                TcpClient client = null;

                try
                {
                    client = _listener.EndAcceptTcpClient(asyncResult);
                }
                catch (ObjectDisposedException ex)
                {
                    slot.Close();
                    return;
                }

                HandleClient(client);

                try
                {
                    slot.Open(HandleConnection);
                }
                catch (ObjectDisposedException ex)
                {
                    slot.Close();
                    return;
                }
            }

            private void HandleClient(TcpClient client)
            {
                Console.WriteLine("Connected: {0}", client.Client.RemoteEndPoint.ToString());
                client.Close();
            }
        }

        private static void Main(string[] args)
        {
            IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 8080);
            TcpServer server = new TcpServer(endpoint);

            try
            {
                Console.WriteLine("Starting...");
                server.Start();
                Console.WriteLine("Started");
                Console.ReadLine();
                Console.WriteLine("Stopping...");
                server.Stop();
                Console.WriteLine("Stopped");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
    }
}

0 个答案:

没有答案