Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle some asynchronous TcpClient responses?

I use this class for asynchronous client-server TCP network connection in my project.

I most connect to "Remote server" and send and receive data over TCP connection (from another company that we can't change communication method except TCP) in a "Interface Web Service".

This "Interface Web Service" handle "Client Apps" requests, create data and pass to "Remote server" over TCP connection, and pass (response) parsed response of "Remote server" to "Client Apps".

Note that current TCP connection, receive "Remote server" responses with OnDataReceived event. (This event is good and I want to use this event for next steps).

How can access and handle these asynchronous responses and pass complete response for "Client Apps" requests?

For summarize:

  1. Client app send request to Interface service
  2. Interface service create command for Remote server
  3. Remote server response to command from Interface service
  4. Now in Interface service, response handled with OnDataReceived EVENT, that I can not access it from Interface service that handle Client App request. Problem is here...

Look at this image to understand my scenario:

Scenario of communications

like image 314
Sayed Abolfazl Fatemi Avatar asked Aug 25 '15 14:08

Sayed Abolfazl Fatemi


2 Answers

please review the following complete (yet, not optimal) working sample of that class.

note the while loop in the MyHandler.ProcessRequest method.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Web;
using System.Threading.Tasks;

namespace TestApp
{
    class Program
    {

        private static NetConnection fakeServerConnector { get; set; }

        static void Main(string[] args)
        {
            var pageHandler = new MyHandler();
            var tw = Console.Out;
            var builder = new UriBuilder();
            builder.Host = "localhost";
            builder.Port = 80;
            builder.Query = "";

            initFakeServer(8080);

            pageHandler.ProcessRequest(
                new HttpContext(
                    new HttpRequest("index.html", builder.ToString(), ""),
                    new HttpResponse(tw))
                    );

            ConsoleKey key;
            Console.WriteLine(Environment.NewLine + "Press [Enter] or [Esc] to exit!");
            do
            {
                key = Console.ReadKey().Key;
            } while (!(key == ConsoleKey.Enter || key == ConsoleKey.Escape));
        }

        private static void initFakeServer(int Port)
        {
            fakeServerConnector = new NetConnection();
            fakeServerConnector.OnDataReceived += fakeServerConnector_OnDataReceived;
            fakeServerConnector.Start(Port);

        }

        static void fakeServerConnector_OnDataReceived(object sender, NetConnection connection, byte[] e)
        {
            Console.WriteLine(System.Text.UTF8Encoding.UTF8.GetString(e));
            var msg = System.Text.UTF8Encoding.UTF8.GetBytes("Fake Server says: \"Hi\"");
            connection.Send(msg);
        }
    }

    public class MyHandler : IHttpHandler
    {

        public string HostName { get; set; }
        public int Port { get; set; }
        private NetConnection clientConnector { get; set; }
        private bool isReceived;
        private byte[] responsePayload;

        public bool IsReusable
        {
            get { return false; }
        }



        public void ProcessRequest(HttpContext context)
        {            
            HostName = "localhost";
            Port = 8080;

            clientConnector = new NetConnection();
            clientConnector.OnDataReceived += OnDataReceivedHandler;
            clientConnector.Connect(HostName, Port);
            clientConnector.Send(System.Text.UTF8Encoding.UTF8.GetBytes("Client Connector says: \"Hello World\""));
            while (!isReceived)
            {
                // do nothing; wait for isReceived to become true;
            }
            var responsePayloadText = System.Text.ASCIIEncoding.UTF8.GetString(responsePayload, 0, responsePayload.Length);
            context.Response.Write(responsePayloadText + Environment.NewLine);
        }


        public void OnDataReceivedHandler(object sender, NetConnection connection, byte[] data)
        {
            isReceived = true;
            responsePayload = data;
        }
    }    
}
like image 106
Brett Caswell Avatar answered Sep 29 '22 06:09

Brett Caswell


Thank you for reading and try to help me.

I solve this problem by edit "NetConnection.cs" class and add this method:

public Task<byte[]> SendAndReceiveData(byte[] data, int timeout = 10000)
{
    CheckServerUsedAsClient();
    client.GetStream().Write(data, 0, data.Length);

    Task<byte[]> tskReceive = ReceiveFromAsync(this, timeout, true);
    tskReceive.Wait();

    return tskReceive;
}

and using this method to send request and receive data from "Remote server" like this:

byte[] requestData = createByteArrayCommand();
Task<byte[]> testTask = netConnectionObj.SendAndReceiveData(requestData);
testTask.Wait();

// testTask.Result <= contains server response
like image 41
Sayed Abolfazl Fatemi Avatar answered Sep 29 '22 06:09

Sayed Abolfazl Fatemi