Multiple socket connections using asynchronous soc

2019-06-13 17:36发布

I have the following code that makes a TCP socket connection to multiple end points as such:

    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);
    }

However, the loop doesn't iterate pass the first IP address, because of the await ReadAsync.

Qn 1) How do I modify this code such that it iterates through my whole list of IPs without "awaiting" for the data be received completely. Do I remove the await keyword from await ReadAsync(client)?
Qn 2) How do I modify this code such that it connects to all the IPs at once. (is this possible?)

1条回答
Evening l夕情丶
2楼-- · 2019-06-13 18:22

How do I modify this code such that it iterates through my whole list of IPs

Your code will iterate the whole list. But it will get to the second address only after it receives all data from the first address.

How do I modify this code such that it connects to all the IPs at once.

If you encapsulate the code for a single address into a separate async method, you can then first call it for each address and then await all the returned Tasks. Or you could use 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);
}
查看更多
登录 后发表回答