【问题标题】:Identify the port on which request is made by client of REQ-REP ZeroMQ application,server is bound to two endpoints(port number)?识别 REQ-REP ZeroMQ 应用程序的客户端发出请求的端口,服务器绑定到两个端点(端口号)?
【发布时间】:2018-08-09 04:02:45
【问题描述】:

服务器绑定到端口#s 上的两个套接字:6666(服务于来自客户端的 SMS 发送请求)和 6661(服务于来自客户端的 EMAIL 发送请求)。

由于我想以不同的方式为它们提供服务,我必须首先知道请求来自哪个端口,以便我可以为该服务执行代码。

那么,我的问题是如何识别端口?

如果这是不可能的,那么可以应用什么逻辑来解决这个问题?

服务器端代码是:

int main () {

zmq::context_t context (1);               // Prepare our context and socket

zmq::socket_t socket  (context, ZMQ_REP); socket.bind  ("tcp://*:6666");
zmq::socket_t socket2 (context, ZMQ_REP); socket2.bind ("tcp://*:6661");

while (true) {      
  // ----------------------------------SMS CODE----------------------------------
     zmq::message_t request;
     socket.recv ( &request);             // Wait for next request from client

  /* ...                                  // SMS Send Logic
     ...
                                          */
     zmq::message_t reply (11);           // Send reply back to client
     memcpy (reply.data (), "SMS Details", 11);
     socket.send (reply);

  // --------------------------------EMAIL CODE----------------------------------
     zmq::message_t request2;
     socket2.recv (&request2);            // Wait for next request from client

  /* ...                                  // Email Send Logic
     ...                           
                                          */
     zmq::message_t reply2 (16);          // Send reply back to client
     memcpy (reply2.data (), "Email Details", 16);
     socket2.send (reply2);
  }                                       // end of while
return 0;
}

【问题讨论】:

    标签: c++ server port zeromq


    【解决方案1】:

    在尝试读取之前,您应该使用zmq::poll 检查哪些套接字有待处理的消息。有一个官方的 cpp 示例here

    您也可以使用 ZMQ_DONTWAIT 来检查消息,但您仍应进行轮询以避免使用过多的 CPU。

    示例:

    #include "zeromq.hpp"
    
    int main (int argc, char *argv[])
    {
        zmq::context_t context(1);
    
        zmq::socket_t emailSocket  (context, ZMQ_REP); emailSocket.bind  ("tcp://*:6666");
        zmq::socket_t smsSocket (context, ZMQ_REP); smsSocket.bind ("tcp://*:6661");
    
        //  Initialize poll set
        zmq::pollitem_t items [] = {
            { emailSocket, 0, ZMQ_POLLIN, 0 },
            { smsSocket, 0, ZMQ_POLLIN, 0 }
        };
        //  Process messages from both sockets
        while (1) {
            zmq::message_t message;
            // wait until there is a message ready for one of the sockets
            zmq::poll (&items [0], 2, -1);
    
            // try to read/process a message from email socket (Don't wait, just skip if there are none)
            if (emailSocket.recv(&message, ZMQ_DONTWAIT)) {
                //  Process email request
                zmq::message_t response(...);
                emailSocket.send(&response);
            }
            // same again for sms socket
            if (smsSocket.recv(&message, ZMQ_DONTWAIT)) {
                //  Process sms request
                zmq::message_t response(...);
                smsSocket.send(&response);
            }
            // back to the top of the loop to wait for another message
        }
        return 0;
    }
    

    【讨论】:

    • 谢谢兄弟。
    • 我阅读了 zmq_poll 的手册页。据我了解,当我们运行此服务器代码时,当调用 poll 函数时,它将无限期地等待,直到两个套接字中的任何一个发生事件。我对吗?你能解释一下接下来会发生什么吗?假设如果收到短信请求呢? if条件表达式什么时候执行。
    • c++ 套接字调用bool socket_t::recv(message_t *msg, int flags = 0) 如果成功接收到消息,则返回true(参见文档api.zeromq.org/2-1:zmq-cpp
    • 您对民意调查是正确的。如果收到短信请求,则 poll 将返回,程序继续。然后您尝试从电子邮件套接字读取,但没有任何内容,因此.recv() 返回 false,然后您跳过它。然后你尝试从 sms 套接字读取,成功了,所以你处理了 sms 请求。
    • 但是文档中给出的两个receive不能连续执行。 Doc Ref-“REQ-REP 套接字对处于同步状态。客户端发出 zmq_send(),然后发出 zmq_recv(),在一个循环中(或一次,如果这就是它所需要的)。执行任何其他序列(例如,发送两条消息a row) 将导致 send 或 recv 调用的返回码为 -1。类似地,服务会按顺序发出 zmq_recv() 然后 zmq_send(),只要它需要。"
    【解决方案2】:

    让我们揭开问题的神秘面纱并清理代码

    代码主要是错误的,不会编译(检查那里不匹配的大括号)。

    接下来,您的代码与您的文本说明不匹配(检查交换的端口号文本是否显示 6666 用于电子邮件,而代码实现此用于 SMS 处理)。

    最后,即使是更正后的代码也不能很好地防止陷入相互的、主要是不可挽救的死锁(在 StackOverflow 或其他地方阅读有关此in many other posts be it here 的更多信息)。


    然而,问题要求检测端口号。

    鉴于在两种 .bind() 方法中分配的端口号已将 ZeroMQ-socket 实例对分离地映射到不同的端口#-s,因此对消息毫无疑问到达,来自哪个socket-instance{ socket | socket2 }这样的消息已经到达。

    鉴于此,所有 SMS 指定的消息都来自端口 6666

    鉴于此,所有 MAIL 指定的消息都来自端口 6661(除非发生了一些发送方有意的破坏,但这超出了问题的范围,不吗?)

    • 我的问题是,我们将如何根据发出请求的端口号有选择地运行 SMS 或 EMAIL 代码。@user3666197 – Ayush Bajaj 32 分钟前?

    否定,先生,您的问题是“我如何识别端口?” - 即如何检测端口#,而您的代码主要是错误的,无论是语法还是语义设计。

    • 已删除语法错误。我了解代码进入死锁状态。这可以通过运行 SMS 或 EMAIL 代码来避免,具体取决于请求所在的端口。 – Ayush Bajaj 21 分钟前

    否定,先生,您的代码设计建议使用命令式 pure-[SERIAL] 计划在第一次期望从 SMS 入口访问端口读取时进入阻塞等待状态#:6666 并且当且仅当这确实发生在未来的某个时间(永远不能保证确实发生),然后代码可能会进入下一个(再次阻塞)等待状态和一直等到一些(如果有的话)EMAIL 入口消息(希望)到达。

    • 您写道“毫无疑问,在消息到达时,这样的消息是从哪个 socket-instance { socket | socket2 } 到达的。”您如何知道请求到达的端口(请提供代码),以便我们可以相应地为它提供服务 – Ayush Bajaj 17 分钟前

    (请编码)?!?
    您是否要求其他人完成这项工作并编写解决方案?

    抱歉,这不是任何志愿服务网站。

    如果您已将问题从“我如何识别端口?”转移到像 (cit.:)这样的命令坚持其他人> “请编码”,请先重新阅读有关使用 poll() 的 ZeroMQ API 文档并正确完成工作,无需要求其他人这样做。

    StackOverflow 社区热衷于帮助解决问题,这些问题已通过 MCVE 公式制定,说明什么可行,但不可行,而 MCVE-code-sn-ps 确实代表了一个人先前研究和设计的有力证据+ 调试工作,显然不是 O/P 代码的情况,也不是进一步转移问题方向的情况。

    永远不要问“(请输入代码)”

    【讨论】:

    • 我的问题是我们将如何根据请求所在的端口号有选择地运行 SMS 或 EMAIL 代码。@user3666197
    • 删除了语法错误。我了解代码进入死锁状态。这可以通过运行 SMS 或 EMAIL 代码来避免,具体取决于请求所在的端口。
    • 您写道“毫无疑问,消息到达时,来自哪个套接字实例 { socket | socket2 } 这样的消息已经到达。”您如何知道请求到达的端口(请提供代码),以便我们可以相应地为它提供服务
    • 回答这个问题比写这篇长篇大论容易
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 2011-07-29
    • 2010-09-25
    • 1970-01-01
    • 2013-09-03
    相关资源
    最近更新 更多