Существует ли общая схема взаимодействия современных основных приложений и демонов Asp.Net?
На самом деле, размещенная служба пока не так мощна.Поэтому люди обычно используют третий продукт.Тем не менее, можно общаться с размещенным сервисом и контроллером.Я буду использовать ваш код в качестве примера для достижения этих целей:
-
TcpServer
может получать две команды, чтобы мы могли переключать состояние размещенной службы с TcpClient
. - Контроллер
WebServer
может вызывать метод TcpServer
косвенно (через посредника) и отображать его как html
Не стоит связывать контроллер с размещенным сервисом.Чтобы вызвать метод из размещенного сервиса, мы можем ввести посредника.Посредник - это не более чем служба, которая служит в качестве одноэлементной (поскольку на нее ссылается размещенная служба):
public interface IMediator{
event ExecHandler ExecHandler ;
string Exec1(string status);
string Exec2(int status);
// ...
}
public class Mediator: IMediator{
public event ExecHandler ExecHandler ;
public string Exec1(string status)
{
if(this.ExecHandler==null)
return null;
return this.ExecHandler(status);
}
public string Exec2(int status)
{
throw new System.NotImplementedException();
}
}
Хостированная служба должна осознавать существование IMediator
и предоставлять свой метод для IMediator
некоторым образом:
public class Netcat : BackgroundService
{
private IMediator Mediator ;
public Netcat(IMediator mediator){
this.Mediator=mediator;
}
// method that you want to be invoke from somewhere else
public string Hello(string status){
return $"{status}:returned from service";
}
// method required by `BackgroundService`
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
TcpListener listener = new TcpListener(IPAddress.Any, 8899);
listener.Start();
while(!stoppingToken.IsCancellationRequested)
{
// ...
}
}
}
Чтобы разрешить управление состоянием из NetCat TcpServer
, я позволяю клиентам получать две команды для переключения состояния фоновой службы:
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
TcpListener listener = new TcpListener(IPAddress.Any, 8899);
listener.Start();
while(!stoppingToken.IsCancellationRequested)
{
TcpClient client = await listener.AcceptTcpClientAsync();
Console.WriteLine("a new client connected");
NetworkStream stream = client.GetStream();
while (!stoppingToken.IsCancellationRequested)
{
byte[] data = new byte[1024];
int read = await stream.ReadAsync(data, 0, 1024, stoppingToken);
var cmd= Encoding.UTF8.GetString(data,0,read);
Console.WriteLine($"[+] received : {cmd}");
if(cmd=="attach") {
this.Mediator.ExecHandler+=this.Hello;
Console.WriteLine($"[-] exec : attached");
continue;
}
if(cmd=="detach") {
Console.WriteLine($"[-] exec : detached");
this.Mediator.ExecHandler-=this.Hello;
continue;
}
await stream.WriteAsync(data, 0, read, stoppingToken);
stream.Flush();
}
}
}
Если вы хотите вызвать метод фоновой службы в контроллере, просто введите IMediator
:
public class HomeController : Controller
{
private IMediator Mediator{ get; }
public HomeController(IMediator mediator){
this.Mediator= mediator;
}
public IActionResult About()
{
ViewData["Message"] = this.Mediator.Exec1("hello world from controller")??"nothing from hosted service";
return View();
}
}