使用异步套接字的多个套接字连接

时间:2013-07-05 10:02:28

标签: c# sockets asynchronous task-parallel-library async-await

我有以下代码,它使TCP套接字连接到多个端点:

    private async void button1_Click(object sender, EventArgs e)
    {
        var listofIps = new List<string> { "192.168.168.193", "192.168.168.221" };
        foreach (var ip in listofIps)
        {
            IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(ip), 4001);
            Socket client = new Socket(AddressFamily.InterNetwork,
                                       SocketType.Stream, ProtocolType.Tcp);
            sockets.Add(client);
            await client.ConnectTaskAsync(remoteEP);
            await ReadAsync(client);
        }
    }

    async Task ReadAsync(Socket s)
    {            
        var args = new SocketAsyncEventArgs();
        args.SetBuffer(new byte[1024], 0, 1024);

        var awaitable = new SocketAwaitable(args);

        while (true)
        {
            await s.ReceiveAsync(awaitable);
            int bytesRead = args.BytesTransferred;
            if (bytesRead <= 0) break;

            var data = new ArraySegment<byte>(args.Buffer, 0, bytesRead);
            AppendLog("RX: " + data.DumpHex());
        }
    }

    public static string DumpHex(this ArraySegment<byte> data)
    {
        return string.Join(" ", data.Select(b => b.ToString("X2")));
    }

    public static Task ConnectTaskAsync(this Socket socket, EndPoint endpoint)
    {            
        return Task.Factory.FromAsync(socket.BeginConnect, socket.EndConnect, endpoint, null);
    }

但是,由于等待ReadAsync,循环不会迭代传递第一个IP地址。

Qn 1)如何修改此代码,使其遍历我的整个IP列表,而无需等待&#34;等待&#34;完全接收数据。我是否从等待await中删除了ReadAsync(client)关键字? Qn 2)如何修改此代码,使其一次连接到所有IP。 (这可能吗?)

1 个答案:

答案 0 :(得分:3)

  

如何修改此代码,使其遍历我的整个IP列表

您的代码迭代整个列表。但只有在收到第一个地址的所有数据后才会到达第二个地址。

  

如何修改此代码,使其一次连接到所有IP。

如果您将单个地址的代码封装到单独的async方法中,则可以先为每个地址调用它,然后await将所有返回的Task调用。或者您可以使用LINQ:

private async void button1_Click(object sender, EventArgs e)
{
    var listOfIps = new List<string> { "192.168.168.193", "192.168.168.221" };
    await Task.WhenAll(listOfIps.Select(ip => ReadFromAddress(ip)));
}

private async Task ReadFromAddress(string address)
{
    IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(ip), 4001);
    Socket client = new Socket(AddressFamily.InterNetwork,
                               SocketType.Stream, ProtocolType.Tcp);
    sockets.Add(client);
    await client.ConnectTaskAsync(remoteEP);
    await ReadAsync(client);
}