多个 Tcp 侦听器不工作

本文关键字:工作 侦听器 Tcp 多个 | 更新日期: 2023-09-27 18:31:34

我做了一个"Acceptor"类,在cunstroctator中它接受一定数量的TcpListeners。从端口 8484 及更高版本开始。

  class Acceptor
{
    private List<TcpListener> Listeners;
    private static int clientCount = 0;
    private static int portStart = 8484;
    public Acceptor(int capacity)
    {
        Listeners = new List<TcpListener>(capacity);
        for (int i = 0; i < capacity; i++)
        {
            Listeners.Add(new TcpListener(IPAddress.Any, portStart));
            portStart++;
        }
        foreach (TcpListener listener in Listeners)
        {
            try
            {
                listener.Start();
                listener.BeginAcceptSocket(new AsyncCallback(EndAccept), null);
            }
            catch (SocketException ex)
            {
                Debug.WriteLine("Failed to start TcpListener, Error {0}.", ex.Message);
            }
        }
        Debug.WriteLine(string.Format("Initiated {0} Listeners from 8484 - {1}.", capacity, portStart));
    }
    public void EndAccept(IAsyncResult IAR)
    {
        TcpListener Listener = (TcpListener)IAR.AsyncState;
        Socket socket = Listener.EndAcceptSocket(IAR);
        frmMain.Clients.Add(clientCount, new Client(socket));
        Listener.Stop();
        Listener = null;
        clientCount++;
        frmMain.Instance.UpdateClients();  
    }
}

但是,这行不通。接受新连接时程序崩溃,为什么会这样?

多个 Tcp 侦听器不工作

您将 null 作为 BeginAcceptSocket 中的"状态"传递,因此当您尝试将其转换回去然后使用它时会出现错误。

尝试更改此行:

listener.BeginAcceptSocket(new AsyncCallback(EndAccept), null);

自:

listener.BeginAcceptSocket(new AsyncCallback(EndAccept), listener);

这是我实现侦听器的方式:

public class EasySocketListener : IDisposable
{
    private Socket _socket;
    public void Start(int port)
    {
        _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        _socket.Bind(new IPEndPoint(IPAddress.Any, port));
        _socket.Listen(1);
        StartAccepting();
    }
    private void StartAccepting()
    {
        try
        {
            _socket.BeginAccept((asyncResult) =>
            {
                try
                {
                    Socket clientSocket = _socket.EndAccept(asyncResult);
                    if (OnSocketAccept != null)
                        OnSocketAccept(this, new SocketEventArgs(clientSocket));
                    StartAccepting();
                }
                catch { }
            }, null);
        }
        catch { }
    }
    public void Dispose()
    {
        if (_socket != null)
        {
            _socket.Dispose();
            _socket = null;
        }
    }
    public event EventHandler<SocketEventArgs> OnSocketAccept;
}

这可以接受多个客户端套接字。当客户端连接时,OnSocketAccept 会触发。

需要套接字事件参数:

public class SocketEventArgs : EventArgs
{
    public Socket Socket { get; private set; }
    public SocketEventArgs(Socket socket)
    {
        Socket = socket;
    }
}

例:

private void Init()
{
    _listener = new EasySocketListener();
    _listener.OnSocketAccept += Listener_OnSocketAccept;
    _listener.Start(port);
}
private void Listener_OnSocketAccept(object sender, SocketEventArgs e)
{
    Debug.WriteLine( e.Socket.RemoteEndPoint );
}

这将出现在我的博客 http://csharp.vanlangen.biz,但还没有写在那里。您可以找到一些从套接字读取异步的方法。