Как обрабатывать некоторые асинхронные ответы TcpClient?
Я использую этот класс для асинхронного клиент-серверного сетевого соединения TCP в моем проекте.
Я чаще всего подключаюсь к " Remote server
" и отправляю и получаю данные по TCP-соединению (от другой компании, которая не может изменить метод связи, кроме TCP) в " Interface Web Service
".
Эта " Interface Web Service
" обрабатывает запросы " Client Apps
", создает данные и передает их " Remote server
" по TCP-соединению, а также передает (ответ) проанализированный ответ " Remote server
" в " Client Apps
".
Обратите внимание, что текущее TCP-соединение получает ответы " Remote server
" с событием OnDataReceived
. (Это событие хорошо, и я хочу использовать это событие для следующих шагов).
Как можно получить доступ к этим асинхронным ответам и обработать их, а также передать полный ответ на запросы " Client Apps
"?
Для подведения итогов:
-
Client app
отправляет запрос в Interface service
- Команда создания
Interface service
для Remote server
- Ответ
Remote server
на команду из Interface service
- Теперь в
Interface service
, ответ обрабатывается с помощью OnDataReceived
, что я не могу получить к нему доступ из Interface service
который обрабатывает запрос Client App
. Проблема здесь...
Посмотрите на это изображение, чтобы понять мой сценарий:
![Scenario of communications]()
Ответы
Ответ 1
Спасибо за чтение и постараюсь помочь мне.
Я решаю эту проблему, редактируя класс "NetConnection.cs" и добавляя этот метод:
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;
}
и используя этот метод для отправки запроса и получения данных с "удаленного сервера" следующим образом:
byte[] requestData = createByteArrayCommand();
Task<byte[]> testTask = netConnectionObj.SendAndReceiveData(requestData);
testTask.Wait();
// testTask.Result <= contains server response
Ответ 2
просмотрите следующую полную (но не оптимальную) рабочую выборку этого класса.
Обратите внимание на цикл while в методе MyHandler.ProcessRequest
.
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;
}
}
}
Ответ 3
Другое решение, которое я тестирую и работаю очень хорошо, SignalR.
С концентратором SignalR мы можем вызвать метод на Interface Web Service
, который похож на запрос на получение от Client Applications
, а затем создать запрос TCP для Remote server
.
После получения ответа от Remote server
(raise OnDataReceive(byte[])
) вызовите метод Client Applications
и передайте ответ.