异步套接字服务器监听多个地址

时间:2014-03-11 00:34:23

标签: c# sockets asynchronous

我需要一个侦听多个IP地址的异步套接字服务器。基本上我想要做的是将这个循环转换为多个地址:

        while (true) {
            // Set the event to nonsignaled state.
            allDone.Reset();

            // Start an asynchronous socket to listen for connections.
            Console.WriteLine("Waiting for a connection...");
            listener.BeginAccept( 
                new AsyncCallback(AcceptCallback),
                listener );

            // Wait until a connection is made before continuing.
            allDone.WaitOne();
        }

在CI中可以使用WSAAsyncSelect和FD_ACCEPT消息来处理它,或者我可以使用IO完成端口,但在C#中我丢失了,也许我没有向Google提出正确的问题,因为我还没有找到任何有用的东西。请帮忙!!

此代码是根据我正在努力的示例复制的,您可以找到它here

2 个答案:

答案 0 :(得分:1)

我相信你所要求的是在没有循环的情况下接受多个连接?

诀窍是在回调中使用调用BeginAccept。

如下所示:

StartListening(){
  listener.Bind(localEndPoint);
  listener.Listen(100);
  GetNewConnection(listener);
}

private GetNewConnection (Socket listener){
  Console.WriteLine("Waiting for a connection...");
  listener.BeginAccept(new AsyncCallback(OnNewConnection),
                       listener);
}

private OnNewConnection(IAsyncResult ar){
  Socket listener = (Socket) ar.AsyncState;
  Socket handler = listener.EndAccept(ar);
  GetNewConnection(listener);
  //... 
}

处理程序是远程IP的套接字,可以有许多。

编辑:如果他们需要绑定到其他地址,您可以使用所需的多个不同侦听器来创建当前调用GetNewConnection

答案 1 :(得分:0)

您可以使用async创建Task.Factory.FromAsync方法,然后使用该方法创建所有连接任务,然后在循环中启动它们,然后调用Task.WaitAll等待所有要建立的联系。请注意,Task.WaitAll是阻止调用,如果需要异步调用,请使用Task.WhenAll

所以也许这样的事情可以完成这项工作(未经测试,但编译)

public static void Connect(List<IPAddress> ipAddresses) 
{
    var listeners = new List<Socket>();
    var tasks = new List<Task<Socket>>();

    foreach (var ipAddress in ipAddresses)
    {
        IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
        Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );
        listeners.Add(listener);        
        listener.Bind(localEndPoint);
        listener.Listen(100);   

        tasks.Add(AcceptTaskAsync(listener));
    }   

    Task.WaitAll(tasks.ToArray());
}

public static async Task<Socket> AcceptTaskAsync(Socket listener)
{
    return await Task<Socket>.Factory.FromAsync(listener.BeginAccept, listener.EndAccept, TaskCreationOptions.DenyChildAttach);
}