jjzjj

c# - Topshelf 服务(充当 TCP 服务器)与自托管 OWIN WebAPI 之间的通信

coder 2023-09-19 原文

我有一个用作 TCP 服务器的 Topshelf Windows 服务。在此服务中,我还有一个自托管 (OWIN) WebAPI。

我的目标是以某种方式允许 WebAPI 与同一服务中包含和运行的 TCP 服务器进行通信。自然地,我可以简单地使用诸如“触发器”文件或共享数据库之类的东西可以经常进行轮询,但我想知道实现此目的的任何更优化/ native 方法。

为了更好地了解该项目,请考虑使用我的 API 并使用任意字符串参数进行某些调用的单页应用程序。然后应将此数据传递给连接到正在运行的 TCP 服务器的客户端(使用 winsock 的 C++ 控制台应用程序)。

以下容器被实例化并传递给 Topshelf HostConfigurator

class ContainerService
{
    private APIService _apiService;
    private EngineService _engineService;
    protected IDisposable WebAppHolder { get; set; }

    public bool Start(HostControl hostControl)
    {
        var host = hostControl;
        _apiService = new APIService();
        _engineService = new EngineService();

        // Initialize API service
        if (WebAppHolder == null)
        {
            WebAppHolder = _apiService.Initialize();
        }

        // Initialize Engine service
        _engineService.Initialize();

        return true;
    }

    public bool Stop(HostControl hostControl)
    {
        // Stop API service
        if (WebAppHolder != null)
        {
            WebAppHolder.Dispose();
            WebAppHolder = null;
        }

        // Stop Engine service
        _engineService.Stop();

        return true;
    }
}

程序入口点中的标准 Topshelf 内容(如上所述):

HostFactory.Run(hostConfigurator =>
{
      hostConfigurator.Service<ContainerService>(containerService =>
      {
           containerService.WhenStarted((service, control) => service.Start(control));
           containerService.WhenStopped((service, control) => service.Stop(control));
      });

      hostConfigurator.RunAsLocalSystem();
      hostConfigurator.SetServiceName("Educe Service Host");
      hostConfigurator.SetDisplayName("Communication Service");
      hostConfigurator.SetDescription("Responsible for API and Engine services");
});

TCP 服务器:

public void Initialize()
{
     _serverListener = new TcpListener(new IPEndPoint(hostAddress, (int)port));
     _serverListener.Start();

     _threadDoBeginAcceptTcpClient = new Thread(() => DoBeginAcceptTcpClient(_serverListener));
     _threadDoBeginAcceptTcpClient.Start();
}

...

    public void DoBeginAcceptTcpClient(TcpListener listener)
    {
        while(!_breakThread)
        { 
            // Set the event to nonsignaled state.
            TcpClientConnected.Reset();

            // Start to listen for connections from a client.
            Console.WriteLine("Waiting for a connection...");

            // Accept the connection. 
            listener.BeginAcceptTcpClient(DoAcceptTcpClientCallback, listener);

            // Wait until a connection is made and processed before continuing.
            TcpClientConnected.WaitOne();
        }
    }

    // Process the client connection.
    public void DoAcceptTcpClientCallback(IAsyncResult ar)
    {
        // Get the listener that handles the client request.
        TcpListener listener = (TcpListener)ar.AsyncState;

        // End the operation and display the received data on the console.
        Console.WriteLine("Client connection completed");
        Clients.Add(listener.EndAcceptTcpClient(ar));

        // Signal the calling thread to continue.
        TcpClientConnected.Set();
    }

WebAPI Controller :

public class ValuesController : ApiController
{
     // GET api/values/5
     public string Get(int id)
     {
          return $"Foo: {id}";
     }
}

如前所述,我寻求的是WebAPI与windows服务之间的“通信”。如何将 WebAPI 调用中的“id”参数传递到我的 Windows 服务中的 _engineService 对象?也许类似于 WPF 的 MVVM Light Messenger?这个想法是它会被解析并发送到存储在客户端列表中的适当的 TcpClient。

任何关于如何实现这一目标的建议将不胜感激。请随时要求澄清/更多代码。

最佳答案

您找到问题的答案了吗?

我不太明白你在寻找他们两个之间的交流时试图达到什么目的?您是否希望以某种方式依赖 TCP/IP 来中继此 ID 或内存中的中继?

潜在地,您可以考虑调解器模式并使用这种在我理解的情况下似乎非常有用的库:https://github.com/jbogard/MediatR

在更简单的方法中,我将依靠事件来实现您想要做的事情,即从 HTTP 请求到 C++ 用户的响应式(Reactive)通信。

我了解您的需求吗?我很好奇解决方案

关于c# - Topshelf 服务(充当 TCP 服务器)与自托管 OWIN WebAPI 之间的通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41556103/

有关c# - Topshelf 服务(充当 TCP 服务器)与自托管 OWIN WebAPI 之间的通信的更多相关文章

  1. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  3. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  4. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

  5. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  6. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  7. ruby-on-rails - `a ||= b` 和 `a = b if a.nil 之间的区别? - 2

    我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行

  8. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  9. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  10. ruby-on-rails - 在 Rails 中调试生产服务器 - 2

    您如何在Rails中的实时服务器上进行有效调试,无论是在测试版/生产服务器上?我试过直接在服务器上修改文件,然后重启应用,但是修改好像没有生效,或者需要很长时间(缓存?)我也试过在本地做“脚本/服务器生产”,但是那很慢另一种选择是编码和部署,但效率很低。有人对他们如何有效地做到这一点有任何见解吗? 最佳答案 我会回答你的问题,即使我不同意这种热修补服务器代码的方式:)首先,你真的确定你已经重启了服务器吗?您可以通过跟踪日志文件来检查它。您更改的代码显示的View可能会被缓存。缓存页面位于tmp/cache文件夹下。您可以尝试手动删除

随机推荐