Linux 编程 —— 进程间的通信 之 消息队列(zmq socket 学习笔记)

15 篇文章 1 订阅
1 篇文章 1 订阅

文档声明:
以下资料均属于本人在学习过程中产出的学习笔记,如果错误或者遗漏之处,请多多指正。并且该文档在后期会随着学习的深入不断补充完善。感谢各位的参考查看。


笔记资料仅供学习交流使用,转载请标明出处,谢谢配合。
如果存在相关知识点的遗漏,可以在评论区留言,看到后将在第一时间更新。
作者:Aliven888

1、ZMQ Socket

  Thread safety: ZeroMQ 的 socket 是非线程安全的,并且 ZeroMQ 本身不建议在多个线程中传递同一个 Socket,即使保证了线程同步。

详细介绍,可以参考下这篇文章 https://www.cnblogs.com/dvwei/p/3608119.html

  Socket types: ZeroMQ一共具有12种类型的socket,5种消息模式。

  • 请求/应答模式:ZMQ_REQ、ZMQ_REP、ZMQ_DEALER、ZMQ_ROUTER
  • 发布/订阅模式:ZMQ_PUB、ZMQ_SUB、ZMQ_XPUB、ZMQ_XSUB
  • 管道模式:ZMQ_PUSH、ZMQ_PULL
  • 配对模式:ZMQ_PAIR
  • 本地模式:ZMQ_STREAM

Socket types:

  下面简单介绍下每一种 Socket types 的含义。

Socket types描述
ZMQ_PAIR只能连接到一个端点。
ZMQ_PUB发布者,此类型表明socket为发布者,不可使用zmq_rev(),当静默时,待发送消息都会丢弃。
ZMQ_SUB订阅者,初始的ZMQ_SUB Socket没有订阅任何消息,可以通过设置ZMQ_SUBSRIBE选项来指定需要订阅的消息。ZMQ_SUB Socket没有实现zmq_send函数,所以不能对其调用zmq_send函数
ZMQ_REQ此模式表明此socket用于客户端,zmq_send()和zmq_recv()需被交替调用,发送一次消息,就需接收一次应答。
ZMQ_REP与上面的ZMQ_REP对应,用于服务端接收请求和发送应答,需zmq_recv和zmq_send交替调用。
ZMQ_DEALER此类型是对 request / reply sockets 的扩展;’消息采用循环轮询方式发送给所以连接端,以公平队列方式接收消息.,阻塞且不丢弃 。
ZMQ_ROUTER此类型是对request/reply sockets的扩展;当接收消息时,会自动在消息顶部加入来源地址标识符,公平队列;当发生时去掉这个标识符,并根据这个标识符路由到相应端点,若此端点不存在则丢弃消息。
ZMQ_PULL从上游节点接收消息,消息以公平队列方式从上游上游连接节点接收。没有实现zmq_send() 。
ZMQ_PUSH发送数据给下游节点,采用轮询方式发送,没有zmq_recv(),阻塞不丢弃 。
ZMQ_XPUB与ZMQ_PUB相比,此类型可接收来自来自订阅者的订阅信息 。
ZMQ_XSUB与ZMQ_SUB相比,通过发送订阅信息给发布者来订阅 。
ZMQ_STREAM本地模式。

Socket option:

  概要:通过 zmq_setsockoptzmq_getsockopt 函数来设置/读取指定选项。

//设置参数,有两个接口1int zmq_setsockopt (void *socket, int option_name, const void *option_value, size_t option_len);2)zmp::socket_t::setsockopt(int option_name, const void *option_value);

//获取设置参数,有两个接口1int zmq_getsockopt (void *socket, int option_name, void *option_value, size_t *option_len);2)zmp::socket_t::setsockopt(int option_name, void *option_value);

//下面举例只有 设置 的, 获取的用法一样。
eg:
int iTimeOut = 1;
zmq::context_t ctx(1);
void *sock = zmq_socket(ctx, ZMQ_DEALER);
assert(qskt);
zmq_setsockopt(sock, ZMQ_SNDTIMEO, (const void *)iTimeOut, sizeof(int));

// or
zmq::socket_t sock(ctx, ZMQ_DEALER);
int iTimeOut = 1;
sock.setsockopt(ZMQ_SNDTIMEO, (const void *)iTimeOut); 

Socket option功能
ZMQ_SNDHWM设置指定Socket的发送消息队列的高水位标识(阀值),ZMQ会严格限制发送队列的上限数。0表示无限制。如果达到了这个限制,socket就会进入异常状态,ZMQ此时会采取适当的措施——阻塞或丢弃消息,这取决于socket的类型。
ZMQ_RCVHWM设置指定Socket的接受消息队列的高水位标识(阀值),ZMQ会严格限制接受队列的上限数。0表示无限制。如果达到了这个限制,socket就会进入异常状态,ZMQ此时会采取适当的措施——阻塞或丢弃消息,这取决于socket的类型。
ZMQ_SUBSCRIBEZMQ_SUBSCRIBE选项会在ZMQ_SUB Socket上建立一个消息过滤器。初始的ZMQ_SUB Socket会过滤掉所有的消息,因此必须设置这个选项,否则将收不到任何消息。如果设置一个0长度(option_value)的空值(option_value),ZMQ_SUB Socket会接受所有的消息。设置一个非空值将接受指定的消息。可以在同一个ZMQ_SUB Socket上设置多个过滤器,它将会接受至少一个匹配的消息。
ZMQ_UNSUBSCRIBE此选项用来删除ZMQ_SUB Socket上通过ZMQ_SUBSCRIBE设置过的消息过滤器。如果Socket有多个实例有相同的过滤器,只删除其中一个。
ZMQ_IDENTITY此选项用来设置Socket的身份标识,只能用于请求/答应模式。ROUTER Socket可以根据这个身份标识来路由信息。身份标识的长度规定在1-255 bytes. 由二进制零开头的标识符为ZMQ保留使用。如果两个身份标识相同的Socket连接到同一个对端(ROUTER),结果行为是未定义的。
ZMQ_RCVTIMEO设置Socket的receive操作的超时。如果为0,则zmq_recv会立即返回,如果没有接收到消息,会返回一个EAGAIN错误;如果为-1,Socket会阻塞到有可用消息为止;如果为其他值,Socket要么阻塞达到指定的时间还没接收到可用的消息,返回一个EAGAIN错误,要么在指定时间前接收到可用消息。
ZMQ_SNDTIMEO设置Socket的Send操作的超时。如果为0,则zmq_send会立即返回,如果消息没有发送成功,会返回一个EAGAIN错误;如果为-1,Socket会一直阻塞到消息消息发送完毕;如果为其他值,Socket要么阻塞达到指定的时间还没发送完成,返回一个EAGAIN错误,要么在指定时间前发送完消息。
ZMQ_LINGER
ZMQ_SNDBUF
ZMQ_IMMEDIATE

  ZMQ是一种基于消息队列的多线程网络库,其对套接字类型、连接处理、帧、甚至路由的底层细节进行抽象,提供跨越多种传输协议的套接字。

&emsap; ZMQ 并不是一个对 socket 的封装,不能用它去实现已有的网络协议。它有自己的模式,不同于更底层的点对点通讯模式。

  它有比 tcp 协议更高一级的协议。(当然 ZeroMQ 不一定基于 TCP 协议,它也可以用于进程间和进程内通讯)它改变了通讯都基于一对一的连接这个假设。

2、常用的通讯模式只有三类:

2.1、请求回应模型:

  由请求端发起请求,并等待回应端回应请求。从请求端来看,一定是一对对收发配对的;反之,在回应端一定是发收对。请求端和回应端都可以是 1:N 的模型。通常把 1 认为是 server ,N 认为是 Client 。ZeroMQ 可以很好的支持路由功能(实现路由功能的组件叫作 Device),把 1:N 扩展为 N:M (只需要加入若干路由节点)。从这个模型看,更底层的端点地址是对上层隐藏的。每个请求都隐含有回应地址,而应用则不关心它。

2.1.1、ZMQ_REQ

  一般用于客户端发送请求消息,此类型的 Socket 必须严格要求先发送后接收的顺序。如果发生异常或者当前没有可用的服务(连接),Socket 会阻塞,直到有可用的服务(新的连接到来),再把这个消息发送出去。ZMQ_REQ 类型的 Socket 不会丢弃数据消息的。

  ZMQ_REP 发送消息时会自动在消息顶部插入一个空帧。

特点总结:

  • 可兼容的 Socket types: ZMQ_REP, ZMQ_ROUTER
  • 数据传输: 双向
  • 发送/接收模式: 发送 --> 接收 --> 发送 …
  • 发送路由策略: Round-robin(循环队列)
  • 接收路由策略: Last peer
  • 进入mute状态后: 阻塞
2.1.2、ZMQ_REP

  一般用于服务端接收消息,此类型的 Socket 必须严格遵循先接收后发送的顺序,即:从客户端接收请求消息使用了公平队列,回应客户端时,所有的 reply 都会被路由到最后下达请求的客户端。如果发生异常或者当前没有可用的客户端连接,所有消息都会毫无提示的被丢弃,不会发生阻塞。

特点总结:

  • 可兼容的 Socket types : ZMQ_REQ, ZMQ_DEALER
  • 数据传输: 双向
  • 发送/接收模式: 接收 --> 发送 --> 接收…
  • 发送路由策略: Last peer
  • 接收路由策略: Fair-queued(公平队列)
2.1.3、ZMQ_DEALER

  ZMQ_DEALER 是一种用于请求/答应模式的更高级的扩展 Socket,它可以自由的收发消息,没有 ZMQ_REP/ZMQ_REQ 那样的限制。对于每一个连接,接收消息也是使用了公平队列,发送使用了循环队列(RR)。ZMQ_DEALER 受 ZMQ_RCVHW 和 ZMQ_SNDHW 两个阀值影响(可通过zmq_setsockopt 函数设置),一旦发送或接收队列达到阀值,Socket 就会进入 mute 状态,此时对 DEALER 的任何 zmq_send 操作都会阻塞,直到 mute 状态结束。

  如果当前没有有效的连接,zmq_send操作也会阻塞,直到有新的连接到来为止。DEALER发生阻塞并不会丢弃消息。

注意: 如果ZMQ_DEALER连接到ZMQ_REP,每一个消息包必须包含一个空帧,然后再紧跟着数据包体。

特点总结:

  • 可兼容的 Socket types: ZMQ_ROUTER, ZMQ_REP, ZMQ_DEALER
  • 数据传输: 双向
  • 发送/接收模式: 无限制
  • 发送路由策略: Round-robin(循环队列)
  • 接收路由策略: Fair-queued(公平队列)
  • 进入mute状态后: 阻塞
2.1.4、ZMQ_ROUTER

  ZMQ_ROUTER 是一种用于请求/答应模式的更高级的扩展 Socket,它可以自由的收发消息。当 ZMQ_ROUTER 接收到消息时,会自动在消息顶部加入来源地址标识符,接收消息使用了公平队列。当发送消息时,ZMQ_ROUTER 又会自动去掉这个标识符,并且根据这个标识符路由到相应的端点。

 如果此地址标识的端点不存在,默认会毫无征兆的丢弃消息,除非 ZMQ_ROUTER_MANDATORY 选项设置为1。当队列达到阀值时,Socket 就会进入 mute 状态,此时所有后续发送到此Socket的消息都会被丢弃,直到 mute 状态结束。同样的,如果对端的接收队列达到了阀值,消息也会被丢弃。

  如果 ZMQ_REQ 连接到 ZMQ_ROUTER,从 ZMQ_ROUTER 接收到 ZMQ_REQ 的消息时,除了会在消息前加上来源地址标识符之外,还会加上一个空帧与原消息分隔,因此消息可以包含多个地址标识符和多个数据包体,如:地址和数据体之间必须用空帧分隔;

在这里插入图片描述

发送回应消息给ZMQ_REQ时,必须至少包含一个空帧;

发送消息时,ZMQ_ROUTER会根据第一个地址标识符路由到对应的端点;

特点总结:

  • 可兼容的 Socket types: ZMQ_DEALER, ZMQ_REQ, ZMQ_ROUTER
  • 数据传输: 双向
  • 发送/接收模式: 无限制
  • 接收路由策略: Fair-queued(公平队列)
  • 进入mute状态后: 丢弃消息
2.1.5、实伪代码:
/************** Clinet 实现伪代码  ***************************/
zmq::context_t ctx(1);
zmq::socket_t s(ctx, ZMQ_DEALER);
s.connect("tcp://127.0.0.1:80001");
zmq::message_t msg(1024); // 定义变量并申请空间
memset (msg.data (), 0, 1024); // 初始化空间
memcpy((void *)msg.data(), "hello", 5); //赋值

//先发送,后回复
while(true)
{
	s.send(msg)
	s.recv(&msg)
}

/************** Server 实现伪代码  ***************************/
zmq::context_t ctx(1);
zmq::socket_t s(ctx, ZMQ_DEALER);
s.bind ("tcp://127.0.0.1:80001");  //绑定端口
zmq::message_t msg(1024);// 定义变量并申请空间
memset (msg.data (), 0, 1024);   初始化空间

//先接收,后回复
while(true)
{
	s.recv(&msg)
	s.send(msg)
}

请求应答模式案例:

Client 端:

// zmq_send.cpp

#include <stdio.h>
#include <zmq.hpp>
#include <thread>
#include <unistd.h>
#include <string.h>
#include <iostream>
using namespace std;

#define NET_INFO_LEN 30  //网络信息
#define SEND_DATA_LEN 1024  //雷达数据长度

void zmqSend()
{
    zmq::context_t context;
    context.setctxopt(ZMQ_IO_THREADS, 1); // 设置参数
    zmq::socket_t sock(context, ZMQ_DEALER);
    sock.setsockopt(ZMQ_SNDTIMEO, 1000);  // 设置超时等待时间
    sock.setsockopt(ZMQ_SNDBUF, 1024);    //设置消息缓存空间
    sock.setsockopt(ZMQ_SNDHWM, 50);      //设置最大消息缓存

    sock.connect("tcp://127.0.0.1:20001");  // 设置网络信息

    while(true)
    {
        if(!sock.connected())  //判断连接是否建立成功
        {
            std::cout << "connect err." << std::endl;
            break;
        }

		// 定义变量, 发送数据
        zmq::message_t message(SEND_DATA_LEN);
        memset(message.data(), 'A', SEND_DATA_LEN);
        zmq::detail::recv_result_t result = sock.send(message, zmq::send_flags::none);
        std::cout << "send size = " << static_cast<std::uint32_t>(result.value()) << std::endl;

        sleep(1); // 休眠等待
        //因为不关心回复结果,这里省略
        //sock.recv(&message, zmq::recv_flags::none);
    }
    
    //关闭连接
    context.close();
    sock.close();
}

int main(int argc, char *argv[])
{
	// 开启工作线程
    thread th(zmqSend);
    th.join();
    return 0;
}

Server 端:

// zmq_recv.cpp

#include <stdio.h>
#include <zmq.hpp>
#include <thread>
#include <unistd.h>
#include <string.h>
#include <iostream>
using namespace std;

#define NET_INFO_LEN 30  //网络信息
#define SEND_DATA_LEN 483200  //雷达数据长度

void zmqRecv()
{
    zmq::context_t context;
    context.setctxopt(ZMQ_IO_THREADS, 1);  // 设置参数
    zmq::socket_t sock(context, ZMQ_DEALER);
    sock.setsockopt(ZMQ_RCVTIMEO, 1000); // 设置超时等待时间

    sock.bind("tcp://*:20001"); // 设置监听端口

    while(true)
    {
        if(!sock.connected()) // 判断连接状态
        {
            std::cout << "connect err." << std::endl;
            break;
        }

		// 定义变量,接收数据
        zmq::message_t message;
        zmq::detail::recv_result_t result = sock.recv(message, zmq::recv_flags::none);
        std::cout << "recv size = " << static_cast<std::uint32_t>(result.value()) << std::endl;

		//因为不关心结果回复,这里省略
        //sock.send(message, zmq::send_flags::none);
    }
    
    //关闭连接
    context.close();
    sock.close();
}

int main(int argc, char *argv[])
{
	// 开启工作线程
    thread th(zmqRecv);
    th.join();
    return 0;
}

编译脚本

#!/bin/bash

# 编译 client 端
g++ -std=c++11 -g zmq_send.cpp -o zmqSend -lzmq -lpthread

# 编译 server 端
g++ -std=c++11 -g zmq_recv.cpp -o zmqRecv -lzmq -lpthread

2.2、发布订阅模型:

  这个模型里,发布端是单向只发送数据的,且不关心是否把全部的信息都发送给订阅端。如果发布端开始发布信息的时候,订阅端尚未连接上来,这些信息直接丢弃。不过一旦订阅端连接上来,中间会保证没有信息丢失。同样,订阅端则只负责接收,而不能反馈。如果发布端和订阅端需要交互(比如要确认订阅者是否已经连接上),则使用额外的 socket 采用请求回应模型满足这个需求。

  ZeroMQ的订阅发布模式是一种单向的数据发布,当客户端向服务端订阅消息之后,服务端便会将产生的消息源源不断的推送给订阅者。

在这里插入图片描述

参考文章:https://www.cnblogs.com/mysky007/p/12288729.html

特点:

1.一个发布者,多个订阅者的关系,1:n;
2.当发布者数据变化时发布数据,所有订阅者均能够接收到数据并处理,这就是发布/订阅模式。

注意事项:

  1. 使用SUB设置一个订阅时,必须使用zmq_setsockopt()对消息进行过滤 zmq_setsockopt (zmq_socket, ZMQ_SUBSCRIBE, filter<订阅信息>, strlen (filter))
	 //这里是需要设置channel,也就是发送的数据的开头,这里设置为nullptr,
	 //长度为 0 ,意思是对接收的消息不过滤
	 socket.setsockopt(ZMQ_SUBSCRIBE, nullptr, 0); 
	 
	 //只接收以AB开头的消息,2为AB的长度。
	 socket.setsockopt(ZMQ_SUBSCRIBE, "AB", 2)
 
  1. 发布者使用PUB套接字将消息发送到队列中,订阅者使用SUB套接字从队列中源源不断的接收消息。新的订阅者可以随时加入,但之前的消息是无法接收到的;已有的订阅者可以随时退出;订阅者还可以添加“过滤器”用来有选择性的接收消息。
2.2.1、ZMQ_PUB

  ZMQ_PUB 类型的 Socket 以发布者的身份向订阅者分发消息,消息以扇出的形式发送给所有订阅者连接。

  ZMQ_PUB 类型的 Socket 没有实现 zmq_recv 函数,所以不能对其调用 zmq_recv 函数!

  当 ZMQ_PUB 的 Socket 达到阀值时进入 mute 状态,此时后续发送的消息会被丢弃,知道 mute 状态结束。

  对 ZMQ_PUB 的 Socket 调用 zmq_send 永远不会发生阻塞。

特点总结:

  • 可兼容的Socket types: ZMQ_SUB, ZMQ_XSUB
  • 数据传输: 单向
  • 发送/接收模式: 只能发送
  • 接收路由策略: Fan out(扇出)
  • 进入mute状态后: 丢弃消息
2.2.2、ZMQ_SUB

  ZMQ_SUB 类型的 Socket 以订阅者的身份接收消息。初始的 ZMQ_SUB 的 Socket 没有订阅任何消息,可以通过设置 ZMQ_SUBSRIBE 选项来指定需要订阅的消息。

  ZMQ_SUB 的 Socket 没有实现 zmq_send 函数,所以不能对其调用 zmq_send 函数!

特点总结:

  • 可兼容的Socket types: ZMQ_PUB, ZMQ_XPUB
  • 数据传输: 单向
  • 发送/接收模式: 只能接收
  • 接收路由策略: Fair-queued(公平队列)
2.2.3、实现伪代码:
/************** 发布端 实现伪代码  ***************************/
void  pubImage()
{
     zmq::context_t context(1);
     zmq::socket_t socket(context, ZMQ_PUB);
     socket.bind("tcp://192.168.0.100:5555");   // 这里是绑定地址
     while (true) 
     {
     	zmq::message_t msg(data_encode.size());
      	memcpy(msg.data(), data_encode.data(), data_encode.size());
      	socket.send(msg); // 发送数据
     }
}




/************** 订阅端 实现伪代码  ***************************/
void subscribe()
{
   	zmq::context_t ctx(1);
    zmq::socket_t socket(ctx, ZMQ_SUB);
    socket.connect("tcp://192.168.0.100:5555");
    这里是需要设置channel,也就是发送的数据的开头,这里设置为nullptr,长度为0 
    //意思是对接收的消息不过滤,如果设置为 socket.setsockopt(ZMQ_SUBSCRIBE, "AB", 2) 
    //只接收以AB开头的消息,2为AB的长度。
    socket.setsockopt(ZMQ_SUBSCRIBE, nullptr, 0); 
    while (true) 
    {
        std::cout <<"subscribe ..." << std::endl;
        zmq::message_t request;
        socket.recv(&request);
    }
}

2.3、管道模型:

  这个模型里,管道是单向的,从 PUSH 端单向的向 PULL 端单向的推送数据流。因为这个模型几乎不怎么使用了,我就没有特意去了解,后面等有时间学习了这方面的知识后在做更新。

3、Socket options(部分)

  通过 zmq_setsockopt 和 zmq_getsockopt 函数来设置/读取指定选项。

3.1、ZMQ_TYPE

ZMQ_TYPE 属性会返回 socket 参数指定的 socket 的类型。socket 的类型是在创建的时候指定的,并且在之后不能修改。

描述类型
Option value type:int
Option value uint:N/A
Default value:N/A
Applicable socket types:all

3.2、ZMQ_SNDHWM

  • 设置指定 Socket 的发送消息队列的高水位标识(阀值),ZMQ 会严格限制发送队列的上限数。0 表示无限制。

  • 如果达到了这个限制,Socket 就会进入异常状态,ZMQ 此时会采取适当的措施——阻塞或丢弃消息,这取决于 Socket 的类型。

注意:ZMQ 不保证 Socket 一定能接受 ZMQ_SNDHWM 这么多的消息,甚至可能会低60%-70%,这取决于socket上的信息流。

描述类型
Option value type:int
Option value uint:message
Default value:1000
Applicable socket types:all

3.3、ZMQ_RCVHWM

  • 设置指定 Socket 的接受消息队列的高水位标识(阀值),ZMQ 会严格限制接受队列的上限数。0表示无限制。

  • 如果达到了这个限制,socket 就会进入异常状态,ZMQ 此时会采取适当的措施——阻塞或丢弃消息,这取决于 socket 的类型。

描述类型
Option value type:int
Option value uint:message
Default value:1000
Applicable socket types:all

3.4、ZMQ_SUBSCRIBE

  • ZMQ_SUBSCRIBE 选项会在 ZMQ_SUB 的 Socket 上建立一个消息过滤器。初始的 ZMQ_SUB 的 Socket 会过滤掉所有的消息,因此必须设置这个选项,否则将收不到任何消息。

  • 如果设置一个 0 长度(option_value)的空值(option_value),ZMQ_SUB 的 Socket 会接受所有的消息。设置一个非空值将接受指定的消息。可以在同一个 ZMQ_SUB 的 Socket 上设置多个过滤器,它将会接受至少一个匹配的消息。

描述类型
Option value type:binary data
Option value uint:N/A
Default value:N/A
Applicable socket types:ZMQ_SUB

3.5、ZMQ_UNSUBSCRIBE

  • 此选项用来删除 ZMQ_SUB 的 Socket 上通过 ZMQ_SUBSCRIBE 设置过的消息过滤器。如果 Socket 有多个实例有相同的过滤器,只删除其中一个。
描述类型
Option value type:binary data
Option value uint:N/A
Default value:N/A
Applicable socket types:ZMQ_SUB

3.6、ZMQ_IDENTITY

  • 此选项用来设置 Socket 的身份标识,只能用于请求/答应模式。ROUTER 的 Socket 可以根据这个身份标识来路由信息。

  • 身份标识的长度规定在 1-255 bytes. 由二进制零开头的标识符为 ZMQ 保留使用。

  • 如果两个身份标识相同的Socket连接到同一个对端(ROUTER),结果行为是未定义的。

描述类型
Option value type:binary data
Option value uint:N/A
Default value:NULL
Applicable socket types:ZMQ_REQ, ZMQ_REP, ZMQ_ROUTER, ZMQ_DEALER

3.7、ZMQ_RCVTIMEO

  • 设置 Socket 的 receive 操作的超时。

  • 如果为0,则 zmq_recv 会立即返回,如果没有接收到消息,会返回一个 EAGAIN 错误;

  • 如果为-1,Socket 会阻塞到有可用消息为止;

  • 如果为其他值,Socket 要么阻塞达到指定的时间还没接收到可用的消息,返回一个 EAGAIN 错误,要么在指定时间前接收到可用消息。

描述类型
Option value type:int
Option value uint:milliseconds
Default value:-1(infinite)
Applicable socket types:all

3.8、ZMQ_SNDTIMEO

  • 设置 Socket 的 Send 操作的超时。

  • 如果为 0,则 zmq_send 会立即返回,如果消息没有发送成功,会返回一个EAGAIN错误;

  • 如果为 -1,Socket 会一直阻塞到消息消息发送完毕;

  • 如果为其他值,Socket 要么阻塞达到指定的时间还没发送完成,返回一个EAGAIN错误,要么在指定时间前发送完消息。

描述类型
Option value type:int
Option value uint:milliseconds
Default value:-1(infinite)
Applicable socket types:all

3.9、ZMQ_LINGER

ZMQ_LINGER 属性会返回 socket 参数指定的 socket 的存留时间。存留时间决定了当 socket 被 zmq_close() 关闭后,将要被发送而没有发送到另一端的消息在内存中能够停留的时间。这会进一步影响与此 socket 相关联的 context 使用 zmq_term() 方式进行终结的结果。

  下面指出了几种不同的行为:

  • 默认值是 -1,指定一个无限的存留时间。在此期间的消息不会由于zmq_close()函数的使用而被终结。试图使用zmq_term()函数来终结于此socket相关联的context的行为会被阻塞,直到消息被发送到对端为止。

  • 属性值是0指明了没有存留时间。当使用zmq_close()关闭socket的时候,消息队列中的消息会被立刻丢弃。

  • 属性值是正数表示会绑定一个毫秒级的正值。在调用zmq_close()函数后,发送消息队列中的消息不会被丢弃;试图使用zmq_term()函数对与socket相关联的context进行终结的操作都会被阻塞,直到所有的消息都被发送到对端,或者停留时间结束了,停留时间结束的时候,消息队列中的所有消息都会被丢弃。

描述类型
属性值类型int
属性值单位毫秒(ms)
默认值-1
可以应用的 socket 类型所有 socket 可用

3.10、ZMQ_SNDBUF

ZMQ_SNDBUF 属性会返回 socket 参数指定的 socket 的底层内核的传输缓存的大小。如果这个值是0,则说明OS的默认值是生效的。要获取更多细节请参考您的操作系统文档中关于SO_SNDBUF的套接字属性。

描述类型
属性值类型int
属性值单位byte
默认值0
可以应用的 socket 类型所有 socket 可用

3.11、 ZMQ_RCVBUF

ZMQ_RCVBUF 属性会返回 socket 参数指定的 socket 的底层内核的接收缓存大小。如果返回值是0,说明OS的默认值在起作用。要获取更多细节请参考您的操作系统文档中关于SO_RCVBUF的套接字属性。

描述类型
属性值类型int
属性值单位byte
默认值0
可以应用的 socket 类型所有 socket 可用

3.12、ZMQ_IMMEDIATE

  返回连接接触的状态值。如果设置为1,回延迟连接上的接触管道,直到底层的连接建立完成了。如果没有其它的连接,这回导致这个socket阻塞;但是会防止在等待连接的期间出现消息队列被填满。

描述类型
属性值类型int
属性值单位布尔
默认值0(否)
可以应用的 socket 类型所有socket可用,当使用TCP/IPC传输方式的时候首先考虑

3.13、ZMQ_RCVMORE

  如果刚刚接到的一帧消息后面还有更多的消息帧,那么 ZMQ_RCVMORE 属性会返回True(1)。如果后面没有剩余的帧了,那么会返回False(0)。

描述类型
属性值类型int
属性值单位布尔
默认值N/A
可以应用的 socket 类型所有socket可用

3.14、ZMQ_AFFINITY

ZMQ_AFFINITY 属性会返回socket参数指定的socket上最新创建的链接的I/O关联。关联决定了这个socket相联系的context的线程池中的哪一个线程来接管新建立的连接。属性值是0表示没有关联,意味着任务会在线程池中的所有线程中公平的分配。对于非0值,最低位的一位(二进制位)对应线程1,次低位对应线程2,等等…例如,值是3表示接下来建立的连接会唯一的被线程1和2接管。

描述类型
属性值类型uint_64
属性值单位N/A
默认值0
可以应用的 socket 类型N/A

3.15、ZMQ_RATE

  返回多路广播数据速率。ZMQ_RATE 选项返回使用 socket 指定的 socket 进行多路广播的时候发送或者接收数据的最大值。

描述类型
属性值类型int
属性值单位kb/s
默认值100
可以应用的 socket 类型当使用多路传输方式时,所有socket可用

3.16、ZMQ_RECOVERY_IVL

  获取多播时的恢复间隔。ZMQ_RECOVERY_IVL 属性会返回 socket 参数指定的 socket 多路广播传输模式时的恢复间隔。恢复时间决定了当一个广播组中不可恢复的消息在被丢弃前,一个接收者在一个广播组里面缺席的最长毫秒时间。

描述类型
属性值类型int
属性值单位毫秒(ms)
默认值10000
可以应用的 socket 类型当使用多路传输方式时,所有socket可用

3.17、

  返回重连时间间隔。ZMQ_RECONNECT_IVL 属性会返回 scoket 指定的 socket 的初始化重连间隔。重连间隔是当使用面向连接的传输方式的时候,在连接断开的时候,ZMQ尝试重新进行连接的等待周期。属性值是 -1 表示不需要重连。

重连周期可能会被 ZMQ 随机选取,以避免当一个 socket 连接了多个对端的时候网络拓扑中出现重连风暴。

描述类型
属性值类型int
属性值单位毫秒(ms)
默认值100
可以应用的 socket 类型面向连接的传输方式时,所有socket可用

3.18、ZMQ_RECONNECT_IVL_MAX

  返回重连间隔的最大值。ZMQ_RECONNECT_IVL_MAX 属性返回 socket 参数指定的 socket 重连间隔的最大值。这个属性是在你两次尝试重连之间等待时间的最大值。在每次重连的时候,重连间隔都会是前一次的两倍,直到到达 ZMQ_RECONNECT_IVL_MAX 。这个属性允许指数补偿策略。默认值是非指数执行方式,并且重连间隔只基于 ZMQ_RECONNECT_IVL

  小于ZMQ_RECONNECT_IVL的值都会被忽略。

描述类型
属性值类型int
属性值单位毫秒(ms)
默认值0(只使用ZMQ_RECONNECT_IVL)
可以应用的 socket 类型面向连接的传输方式时,所有socket可用

3.19、ZMQ_BACKLOG

  返回未解决的链接队列的最大值。ZMQ_BACKLOG 属性返回 socket 参数指定的socket 上未解决的链接队列长度的最大值;这只对面向连接的传输方式有效。要获得更多细节,请参考您的操作系统文档中关于listen函数的部分。

描述类型
属性值类型int
属性值单位链接
默认值100
可以应用的 socket 类型面向连接的传输方式时,所有socket可用

3.20、ZMQ_MAXMSGSIZE

  流入的消息大小的最大值。这个属性会返回流入的消息的限制。如果一个对端发送了一个比 ZMQ_MAXMSGSIZE 长的消息,这个链接就会断开。值是 -1表示没有限制。

描述类型
属性值类型int64_t
属性值单位byte
默认值-1
可以应用的 socket 类型所有socket可用

3.21、ZMQ_MULTICAST_HOPS

  这个属性用于返回向外发送的广播包的存活时间。默认值是 -1,表示这个广播包不能够离开本地网络。

描述类型
属性值类型int
属性值单位网络跳数
默认值-1
可以应用的 socket 类型当使用广播传输方式时,所有socket可用

3.22、ZMQ_IPV6

  返回socket的IPv6状态。返回这个socket的IPv6属性。如果这个值是1,表示IPv6在这个socket上允许使用;如果是0,表示这个socket只能使用IPv4。如果IPv6是可用的,这个socket可以连接/接受IPv4/IPv6主机的连接。

描述类型
属性值类型int
属性值单位bool
默认值0 (否)
可以应用的 socket 类型当使用TCP连接的时候,所有socket可用

3.23、ZMQ_IPV4ONLY

  返回只使用IPv4的socket代理状态。返回这个socket只使用IPv4的属性。这个属性请慎用。

  请使用ZMQ_IPV6属性。

描述类型
属性值类型int
属性值单位bool
默认值1 (是)
可以应用的 socket 类型当使用TCP连接的时候,所有socket可用

3.24、ZMQ_FD

  返回与这个socket联系的文件描述符。ZMQ_FD 属性会返回与这个 socket 相联系的文件描述符。被返回的文件描述符可以被用来把这个socket集成到一个已经存在的事件循环里面; ZMQ 动态链接库会通过标记文件描述符已准备好被读取了,当这个 socket 上有任何事件处于一种边沿触发方式的时候。

  能否从返回的文件描述符中读取数据,不须要指明是否能够从底层的socket中读取或者写入;应用程序必须通过ZMQ_EVENTS属性进行后续的检索,来检查真是的事件状态。

  返回的文件描述符也必须使用 zmq_send 和 zmq_recv 函数在内部使用。因为文件描述符是边缘触发中断的,应用程序在每次调用 zmq_send 或者 zmq_recv 函数进行读取之后都需要更新 ZMQ_EVENTS 的状态。说的更明确:在调用 zmq_send 函数之后,这个 socket 可能变得可读了(反之亦然),但是并没有在这个问价描述符上触发一次读事件。

  返回的文件描述符被设计用于使用poll或者类似的系统调用。应用程序千万不要试图直接对其进行数据读写,也不要试图关闭它。

描述类型
属性值类型在POSIX系统中为int,在Windows系统中为SOCKET
属性值单位N/A
默认值N/A
可以应用的 socket 类型所有socket可用

3.25、ZMQ_EVENTS

  返回socket的事件状态。

ZMQ_EVENTS 属性会返回 socket 参数指定的 socket 的事件状态。返回值是一个由下列事件标志进行或操作的组合:

  • ZMQ_POLLIN:指出至少有一个消息可以在此 socket 上就行非阻塞接收。
  • ZMQ_POLLOUT:指出至少有一个消息可以在此 socket 上进行非阻塞发送。

  被 ZMQ_FD 属性返回的文件描述组合,已经可以被读取数据但是 ZMQ_EVENTS 属性检查后却没有实际的事件返回的情况也是正常的;应用程序只需要简单的忽略这种情况并且重新启动它们的操作/事件循环即可。

描述类型
属性值类型int
属性值单位N/A
默认值N/A
可以应用的 socket 类型所有socket可用

3.26、 ZMQ_LAST_ENDPOINT

  返回最后一个终结点。

ZMQ_LAST_ENDPOINT 属性会返回最后绑定的 TCP/IPC 传输协议的终结点。返回值会是一个 ZMQ DSN 格式的字符串。注意,如果 TCP 主机是 INADDR_ANY,或者是由*指定的,那么返回值会是0.0.0.0(IPv4)。

描述类型
属性值类型以NULL结尾的字符串
属性值单位N/A
默认值NULL
可以应用的 socket 类型当使用TCP/IPC协议的时候,所有socket可用

3.27、 ZMQ_TCP_KEEPALIVE

  返回最后一个终结点

ZMQ_LAST_ENDPOINT 属性会返回最后绑定的 TCP/IPC 传输协议的终结点。返回值会是一个 ZMQ DSN 格式的字符串。注意,如果 TCP 主机是 INADDR_ANY,或者是由*指定的,那么返回值会是 0.0.0.0(IPv4)。

描述类型
属性值类型以NULL结尾的字符串
属性值单位N/A
默认值NULL
可以应用的 socket 类型当使用TCP/IPC协议的时候,所有socket可用

3.28、 ZMQ_TCP_KEEPALIVE

  重写SO_KEEPALIVE socket属性。

  重写SO_KEEPALIVE socket 属性(被OS支持的)。默认值是 -1,表示跳过任何重写操作,并且使用系统的默认值。

描述类型
属性值类型int
属性值单位-1, 0 , 1
默认值-1(使用OS的默认值)
可以应用的 socket 类型当使用TCP协议的时候,所有socket可用

3.29、 ZMQ_TCP_KEEPALIVE_IDLE

  重写 TCP_KEEPCNT(或者一些系统上的TCP_KEEPALIVE)。

  重写TCP_KEEPCNT(或者一些OS上的TCP_KEEPALIVE)属性(被OS支持的)。默认值是 -1,表示跳过任何重写操作并使用OS的默认值。

描述类型
属性值类型int
属性值单位-1, >0
默认值-1(使用OS的默认值)
可以应用的 socket 类型当使用TCP协议的时候,所有socket可用

3.30、 ZMQ_TCP_KEEPALIVE_CNT

  重写TCP_KEEPCNT socket属性。

  重写TCP_KEEPCNT socket属性(被操作系统支持的)。默认值是 -1,表示跳过所有的重写操作并且使用系统的默认值。

描述类型
属性值类型int
属性值单位-1, >0
默认值-1(使用OS的默认值)
可以应用的 socket 类型当使用TCP协议的时候,所有socket可用

3.31、 ZMQ_TCP_KEEPALIVE_INTVL

  重写TCP_KEEPINTVL socket属性。

  重写 TCP_KEEPINTVL socket 属性(被操作系统支持的)。默认值是 -1,表示跳过所有的重写操作,并且使用操作系统的默认值。

描述类型
属性值类型int
属性值单位-1, >0
默认值-1(使用OS的默认值)
可以应用的 socket 类型当使用TCP协议的时候,所有socket可用

3.32、 ZMQ_MECHANISM

  返回当前的安全机制。

  ZMQ_MECHANISM属性返回这个socket当前的安全机制。

描述类型
属性值类型int
属性值单位ZMQ_NULL, ZMQ_PLAIN, 或者ZMQ_CURVE
默认值ZMQ_NULL
可以应用的 socket 类型当使用TCP/IPC协议的时候,所有socket可用

3.33、 ZMQ_PLAIN_SERVER

  返回当前PLAIN服务的角色。

  返回 ZMQ_PLAIN_SERVER 属性,如果有的话,socket 预设的。

描述类型
属性值类型int
属性值单位0,1
默认值int
可以应用的 socket 类型当使用TCP/IPC协议的时候,所有socket可用

3.34、 ZMQ_PLAIN_USERNAME

  返回当前PLAIN的用户名。

  ZMQ_PLAIN_USERNAME属性会返回给PLAIN安全机制最后设置的用户名。返回值必须是一个以NULL结尾的字符串或者空字符串。返回的空间大小应该包括这个结尾的字符字节。

描述类型
属性值类型以NULL结尾的字符串
属性值单位N/A
默认值空字符串
可以应用的 socket 类型当使用TCP/IPC协议的时候,所有socket可用

3.35、 ZMQ_PLAIN_PASSWORD

  返回当前的密码。

  ZMQ_PLAIN_PASSWORD属性返回给PLAIN安全机制最后设置的密码。返回值必须是一个以NULL结尾的字符串或者空字符串。返回的空间大小应该包括这个空字节。

描述类型
属性值类型以NULL结尾的字符串
属性值单位N/A
默认值空字符串
可以应用的 socket 类型当使用TCP/IPC协议的时候,所有socket可用

3.36、 ZMQ_CURVE_PUBLICKEY

  返回当前CURVE的公钥。

  返回此 socket 上当前长期公钥。你可以提供一个32B的存储空间,来接收二进制公钥值,或者41B的存储空间,来接收Z85格式的值。注意:为了能够取得一个可打印的公钥,存储空间必须是41B的大小,40B用来存放公钥值,1B存放空字符。

描述类型
属性值类型二进制数据或Z85字符串
属性值单位32或41
默认值空字符串
可以应用的 socket 类型当使用TCP协议的时候,所有socket可用

3.37、 ZMQ_CURVE_SECRETKEY

  返回当前的CURVE socket 秘钥。

  返回此 socket 的当前长期秘钥。以可以提供一个32B的存储空间,来接收二进制秘钥,或者41B的存储空间,来接收Z85格式的可打印秘钥。

描述类型
属性值类型二进制数据或Z85字符串
属性值单位32或41
默认值空字符串
可以应用的 socket 类型当使用TCP协议的时候,所有socket可用

3.38、 ZMQ_CURVE_SERVERKEY

  返回当前的CURVE服务器码。

  返回客户端 socket 的当前的服务器码。你可以提供32B的存储空间,来接收二进制的值,或者41B的存储空间,来接收Z85格式的可打印值。

描述类型
属性值类型二进制数据或Z85字符串
属性值单位32或41
默认值空字符串
可以应用的 socket 类型当使用TCP协议的时候,所有socket可用

3.39、 ZMQ_ZAP_DOMAIN

  返回RFC 27的认证域。

ZMQ_ZAP_DOMAIN 属性会返回给此 socket 最后设置的 ZAP 域。返回值可能是一个以 NULL 结尾的字符串,或者空字符串。返回的字符串长度应该包括最后的结束字符。

描述类型
属性值类型字符串
属性值单位N/A
默认值无设置
可以应用的 socket 类型当使用TCP协议的时候,所有socket可用

参考文章

https://blog.csdn.net/mysunshinexia01/article/details/80871696
https://www.cnblogs.com/dvwei/p/3608119.html
http://api.zeromq.org/
https://www.cnblogs.com/mysky007/p/12288729.html

  • 4
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt 是一个跨平台的 C++ 应用程序开发框架,而 ZeroMQ(简称 ZMQ)是一个高性能、异步的消息传递库。在 Qt 中使用 ZMQ 实现消息队列需要进行以下几个步骤: 1. 首先,下载并安装 ZMQ 库。你可以从 ZeroMQ 的官方网站(https://zeromq.org/)下载适合你的操作系统的库文件,并按照安装指南进行安装。 2. 在 Qt 项目中添加 ZMQ 的头文件路径和库文件路径。在项目的 .pro 文件中添加以下内容: ```pro INCLUDEPATH += /path/to/zmq/include LIBS += -L/path/to/zmq/lib -lzmq ``` 将上述路径替换为你实际安装 ZMQ 库的路径。 3. 在 Qt 代码中引入 ZMQ 相关的头文件: ```cpp #include <zmq.hpp> ``` 4. 创建一个 ZMQ 的上下文(context)对象和一个 socket 对象: ```cpp zmq::context_t context(1); zmq::socket_t socket(context, ZMQ_PUB); // 这里以发布者(publisher)为例,如果是订阅者(subscriber)则使用 ZMQ_SUB ``` 5. 配置 socket 的连接参数(可选): ```cpp socket.bind("tcp://localhost:5555"); // 绑定到本地地址和端口 ``` 6. 发送消息到消息队列: ```cpp std::string message = "Hello, ZMQ!"; zmq::message_t zmqMessage(message.size()); memcpy(zmqMessage.data(), message.data(), message.size()); socket.send(zmqMessage); ``` 可以根据具体需求自定义消息的格式和内容。 7. 关闭 socket 和 context: ```cpp socket.close(); context.close(); ``` 这样,你就可以在 Qt 中使用 ZMQ 实现消息队列的功能了。当然,这只是一个简单的示例,实际应用可能需要更复杂的逻辑来处理接收和处理消息等操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值