-2

我创建了一个“Acceptor”类,它在 cunstroctor 中接受一定数量的 TcpListener。从端口 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();  
    }
}

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

4

2 回答 2

2

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

尝试更改此行:

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

至:

listener.BeginAcceptSocket(new AsyncCallback(EndAccept), listener);
于 2013-09-16T19:44:33.113 回答
0

这就是我实现监听器的方式:

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 触发。

需要 SocketEventArgs:

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但还没有写在那里。您可以找到一些从套接字异步读取的方法。

于 2013-09-16T20:12:49.033 回答