-1

I'm working on a TCP connection where my client connects to a server's IP on 2 different ports. So I have 2 instances of TcpClient objects, one connecting to the IP on port 9000 and the other on port 9001.

The aim of 2 connections is that the server uses the active connection on port 9000 to give certain responses to the client frequently, and the client uses these responses to form and send a request on port 9001.

Now, the first time I connect on 9000, I get a response, I then form a request and fire off via 9001. Now I have a feeling I'm doing something wrong with the way I'm managing asynchronous requests to both ports, but I can't figure an alternate way of doing this:

    IPAddress IPAddress = IPAddress.Parse("192.168.1.10");

    public static async Task ConnectToPort9000()
    {
        TcpClient TcpClient1 = new TcpClient();
        try
        {
            await TcpClient1.ConnectAsync(IPAddress, 9000);
            if (TcpClient1.Connected)
            {
                byte[] Buffer = new byte[1024];
                while (await TcpClient1.GetStream().ReadAsync(Buffer, 0, Buffer.Length) > 0)
                {
                    //Server returns a message on this port
                    string Port9000Response = Encoding.UTF8.GetString(Buffer, 0, Buffer.Length);

                    //Setting ConfigureAwait(false) so that any further responses returned
                    //on this port can be dealt with
                    await Task.Run(async () =>
                    {
                        await SendRequestToPort9001BasedOnResponseAsync(Port9000Response);
                    }).ConfigureAwait(false);
                }
            }
        }
        catch (Exception)
        {
            throw;
        }
    }

    private async Task SendRequestToPort9001BasedOnResponseAsync(string Port9000Response)
    {
        //Open connection on port 9001 and send request
        TcpClient TcpClient2 = new TcpClient();
        await TcpClient2.ConnectAsync(IPAddress, 9001);

        if (TcpClient2.Connected)
        {
            //Handle each string response differently
            if (Port9000Response == "X")
            {
                //Form a new request message to send on port 9001
                string _NewRequestMesssage = "Y";
                byte[] RequestData = Encoding.UTF8.GetBytes(_NewRequestMesssage);
                new SocketAsyncEventArgs().SetBuffer(RequestData, 0, RequestData.Length);
                await TcpClient2.GetStream().WriteAsync(RequestData, 0, RequestData.Length);
                await TcpClient2.GetStream().FlushAsync();
                //Handle any responses on this port

                //At this point, based on the request message sent on this port 9001
                //server sends another response on **port 9000** that needs separately dealing with
                //so the while condition in the previous method should receive a response and continue handling that response again
            }
            else if (Port9000Response == "A")
            {
                //Do something else
            }
        }
    }

The issue I am having at the moment is, after I send the request on port 9001, when processing any response messages on port 9001, the server has already sent me a response on port 9000, but my while loop on the first method isn't getting triggered, and it seems like that's because it's still executing the second method to process request/response on port 9001. I tried using ConfigureAwait(false) to basically fire and forget, but it doesn't seem to be working. Am I handling asynchronous processes the wrong way? Or should I look at alternatives such as action/delegates?

1 Answers1

0

The aim of 2 connections is that the server uses the active connection on port 9000 to give certain responses to the client frequently, and the client uses these responses to form and send a request on port 9001.

Please don't do this. Socket programming is hard enough without making it extremely more complicated with multiple connections. Error handling becomes harder, detection of half-open connections becomes harder (or impossible), and communication deadlocks are harder to avoid.

Each socket connection is already bidirectional; it already has two independent streams. The only thing you need to do is always be reading, and send as necessary. The read and write streams are independent, so keep your reads and writes independent.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • Totally agreed, but the 2 port connection is beyond my control. The server is a 3rd party integration provider and is configured to serve connections over 2 ports, I have to design a client that can communicate with the server by listening over 2 ports - one for reading responses, and the other to send a request to based on the received response. – Computer Scientist Apr 04 '20 at 01:12