Sockets 从Elixir中的tcp服务器向开放连接中的tcp客户端发送消息

Sockets 从Elixir中的tcp服务器向开放连接中的tcp客户端发送消息,sockets,tcp,elixir,phoenix-framework,gen-tcp,Sockets,Tcp,Elixir,Phoenix Framework,Gen Tcp,通过使用Erlang模块的实现,我在Phoenixframwork中开发了一个TCP服务器 我可以通过调用:gen_tcp.listen(port)启动服务器,然后它会侦听此端口上的新连接 一个客户是药房的自动拣药系统(基本上是一个自动配药机器人) 因此,作为tcp客户端,robot能够打开到我的tcp服务器的连接。服务器通过handle\u info-回调方法侦听机器人发送的新消息,并且还能够在此请求中响应客户端(:gen\u tcp.send) 我面临的问题是,我不知道如何使用此连接并在没有

通过使用Erlang模块的实现,我在Phoenixframwork中开发了一个TCP服务器

我可以通过调用
:gen_tcp.listen(port)
启动服务器,然后它会侦听此端口上的新连接

一个客户是药房的自动拣药系统(基本上是一个自动配药机器人)

因此,作为tcp客户端,robot能够打开到我的tcp服务器的连接。服务器通过
handle\u info
-回调方法侦听机器人发送的新消息,并且还能够在此请求中响应客户端(
:gen\u tcp.send

我面临的问题是,我不知道如何使用此连接并在没有客户端请求的情况下将数据发送回机器人。

由于机器人是tcp客户端(机器人背后的公司表示,目前机器人无法充当服务器),因此没有开放端口/机器人服务器地址可供我发送消息。因此,我必须使用已经建立的由客户端初始化的连接

设置

药房界面>药房api(凤凰城)>机器人(供应商软件)

工作流程:

  • robot通过tcp初始化与api的连接
  • robot向api发送状态信息并获得响应
  • 在某个时刻(参见更新1),api必须向机器人发送分发请求(通过使用#1中初始化的连接)
  • 第1步和第2步工作,第3部分。没有

    对于Elixir/Phoenix中的tcp连接,这看起来是一个相当简单的问题,但任何正确方向的提示都值得高度赞赏:)

    到目前为止,我提出了这个实现(基于此):

    更新1

    在某个点=用户(例如药剂师)在ui前端下订单。前端触发到api的post,api在OrderController中处理post。OrderController必须转换订单(以便robot理解它),并将其传递给TcpServer,后者保持与robot的连接。此工作流每天将发生多次

    { :ok, _sock } = :gen_tcp.accept state.lsock
    
    _sock是您不使用的插座。但实际上,它是一个可以发送数据的套接字。例如:gen_tcp.send(_sock,data)将向您的机器人推送数据。您需要确保正在监视此套接字的断开连接情况,并确保您有权访问它以备将来使用。这意味着您需要创建一个拥有该套接字并包含对该套接字的引用的进程,以便您的服务器代码可以在稍后的时间点向该套接字发送数据。也就是说,最简单的方法就是创建gen_服务器

    但是,您所做的是创建自己的接受程序代码。有一个已经广泛使用的接受池实现。它被称为ranch()。你可以用它来代替自己的滚动。它提供了比你现有的更好的方法。例如,它创建了一个接受者池。它还允许更好地抽象gen_服务器,该服务器只负责与机器人通信,而不必担心侦听器套接字

    _sock是您不使用的插座。但实际上,它是一个可以发送数据的套接字。例如:gen_tcp.send(_sock,data)将向您的机器人推送数据。您需要确保正在监视此套接字的断开连接情况,并确保您有权访问它以备将来使用。这意味着您需要创建一个拥有该套接字并包含对该套接字的引用的进程,以便您的服务器代码可以在稍后的时间点向该套接字发送数据。也就是说,最简单的方法就是创建gen_服务器


    但是,您所做的是创建自己的接受程序代码。有一个已经广泛使用的接受池实现。它被称为ranch()。你可以用它来代替自己的滚动。它提供了比你现有的更好的方法。例如,它创建了一个接受者池。它还允许更好地抽象gen_服务器,该服务器只负责与机器人通信,而不必担心侦听器套接字。

    您能举一个“在某个点”的例子吗?谁将触发这一行动?简单的回答是,如果希望
    TcpServerClean
    能够同时处理多个客户机,您可以生成一个进程(如另一个
    GenServer
    ),该进程存储套接字,等待触发器,然后发送响应。@Dogbert:我更新了我的问题,给出了一个“在某个点”可能是什么的示例。如果在我更新后仍然有效,您介意并给出一个简短的示例吗?谢谢你的帮助!你能举个“在某个时刻”的例子吗?谁将触发这一行动?简单的回答是,如果希望
    TcpServerClean
    能够同时处理多个客户机,您可以生成一个进程(如另一个
    GenServer
    ),该进程存储套接字,等待触发器,然后发送响应。@Dogbert:我更新了我的问题,给出了一个“在某个点”可能是什么的示例。如果在我更新后仍然有效,您介意并给出一个简短的示例吗?谢谢你的帮助!谢谢你给ranch的链接,我不知道接受者代码!我认为你回答的第一部分与达戈伯特在评论中提出的方向相同。我试试看,然后再打给你。我更新了我的问题,以举例说明“在某一点”的含义,只是为了确保这不会改变你的答案。非常感谢。谢谢你给ranch的链接,我不知道接受者代码!我认为你回答的第一部分与达戈伯特在评论中提出的方向相同。我试试看,然后再打给你。我更新了我的问题,以举例说明“在某一点”的含义,只是为了确保这不会改变你的答案。非常感谢。
    { :ok, _sock } = :gen_tcp.accept state.lsock