ZMQ push/pull 模式在两个应用程序之间发送消息,但 tcpdump 显示每个数据包的源和目标是相同的

ZMQ push/pull pattern sends messages between two apps but tcpdump shows that source and destination of each packet are the same

我在学习ZMQ。我创建了两个使用 pull/push 模式相互通信的简单应用程序。我在 Ubuntu 上创建了两个 tap 接口。其中一个的 IP 地址为 1.1.1.1,第二个分路器的 IP 地址为 1.1.1.2。这些应用程序中的每一个都发送一个字符串并写入 stdout 接收到的字符串。一切如我所愿,但是当我 运行 tcpdump 我看到对于每个数据包,源地址和目标地址都是相同的。 tcpdump 还显示 ZMQ 使用我在应用程序中设置的不同端口。 这是我的应用程序 1 的代码:

#include <zmq.hpp>
#include <string>
#include <iostream>
#include <thread>

using namespace std;
using namespace zmq;

int main()
{
    context_t zmq_context = context_t();

    socket_t zmq_send_socket = socket_t(zmq_context, ZMQ_PUSH);
    socket_t zmq_recv_socket = socket_t(zmq_context, ZMQ_PULL);

    string push_socat = "tcp://1.1.1.2:5001";
    string pull_socat = "tcp://1.1.1.1:5000";   

    zmq_send_socket.bind(push_socat.c_str());
    zmq_recv_socket.connect(pull_socat.c_str());
    
    while(1)
    {
        string msg = "app 1 sends";
        message_t received_message;
        if(msg.size())
        {
            message_t send_message(msg);
            zmq_send_socket.send(send_message, send_flags::dontwait);
        }
        auto result = zmq_recv_socket.recv(received_message, recv_flags::dontwait);
        if (result.has_value())
        {   
            cout<<received_message<<endl;                       
        }   
        std::this_thread::sleep_for(std::chrono::milliseconds(3000));           
    }   

}

这是我的应用 2 代码:

#include <zmq.hpp>
#include <string>
#include <iostream>
#include <thread>

using namespace std;
using namespace zmq;

    int main()
        {
            context_t zmq_context = context_t();
        
            socket_t zmq_send_socket = socket_t(zmq_context, ZMQ_PUSH);
            socket_t zmq_recv_socket = socket_t(zmq_context, ZMQ_PULL);
        
            string push_socat = "tcp://1.1.1.1:5000";
            string pull_socat = "tcp://1.1.1.2:5001";   
        
            zmq_send_socket.bind(push_socat.c_str());
            zmq_recv_socket.connect(pull_socat.c_str());
            
            while(1)
            {
                string msg = "app 2 sends";
                message_t received_message;
                if(msg.size())
                {
                    message_t send_message(msg);
                    zmq_send_socket.send(send_message, send_flags::dontwait);
                }
                auto result = zmq_recv_socket.recv(received_message, recv_flags::dontwait);
                if (result.has_value())
                {   
                    cout<<received_message<<endl;                       
                }   
                std::this_thread::sleep_for(std::chrono::milliseconds(3000));           
            }   
        
        }

应用 1 打印“应用 2 发送”,应用 2 打印“应用 1 发送”。

tcpdump 的示例输出:

22:01:51.724290 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 77: 10.100.100.1.5000 > 10.100.100.1.45624: Flags [P.], seq 649:660, ack 1, win 512, options [nop,nop,TS val 62388355 ecr 62385355], length 11
22:01:51.724325 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 66: 10.100.100.1.45624 > 10.100.100.1.5000: Flags [.], ack 660, win 512, options [nop,nop,TS val 62388355 ecr 62388355], length 0
22:01:51.967303 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 79: 10.100.100.2.5001 > 10.100.100.2.41982: Flags [P.], seq 767:780, ack 1, win 512, options [nop,nop,TS val 2441785963 ecr 2441782963], length 13
22:01:51.967335 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 66: 10.100.100.2.41982 > 10.100.100.2.5001: Flags [.], ack 780, win 512, options [nop,nop,TS val 2441785963 ecr 2441785963], length 0
22:01:54.724516 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 77: 10.100.100.1.5000 > 10.100.100.1.45624: Flags [P.], seq 660:671, ack 1, win 512, options [nop,nop,TS val 62391355 ecr 62388355], length 11
22:01:54.724551 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 66: 10.100.100.1.45624 > 10.100.100.1.5000: Flags [.], ack 671, win 512, options [nop,nop,TS val 62391355 ecr 62391355], length 0
22:01:54.967509 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 79: 10.100.100.2.5001 > 10.100.100.2.41982: Flags [P.], seq 780:793, ack 1, win 512, options [nop,nop,TS val 2441788963 ecr 2441785963], length 13
22:01:54.967542 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 66: 10.100.100.2.41982 > 10.100.100.2.5001: Flags [.], ack 793, win 512, options [nop,nop,TS val 2441788963 ecr 2441788963], length 0

你知道为什么源地址和目标地址相同,为什么我能看到奇怪的端口吗?

您获得的结果符合您的端口设置。

如果您查看 bind/connect 端口,您的 push/pull 对套接字都具有相同的 IP 地址。

App1

  zmq_send_socket.bind(tcp://1.1.1.2:5001)

App2 

  zmq_recv_socket.connect(tcp://1.1.1.2:5001);

“奇怪的”端口来自 tcp 连接的连接端。 bind/listen 端使用您指定的端口 (5000/5001),但连接端将使用临时端口。