案例一
这个案例的出处是ZMQ的官网。请求段发送Hello,应答端回复World。
ZMQ
Request(client)
#include <string>
#include <iostream>
#include <zmq.hpp>
using namespace std;
using namespace zmq; // 使用 zmq 命名空间
int main()
{
// initialize the zmq context with a single IO thread
context_t context{1};
// construct a REQ (request) socket and connect to interface
socket_t socket{context, socket_type::req};
socket.connect("tcp://localhost:5555");
// set up some static data to send
const string data{"Hello"};
for (auto request_num = 0; request_num < 10; ++request_num)
{
// send the request message
cout << "Sending Hello " << request_num << "..." << endl;
socket.send(buffer(data), send_flags::none);
// wait for reply from server
message_t reply{};
socket.recv(reply, recv_flags::none);
cout << "Received " << reply.to_string();
cout << " (" << request_num << ")";
cout << endl;
}
return 0;
}
Reply(server)
#include <string>
#include <chrono>
#include <thread>
#include <iostream>
#include <zmq.hpp>
int main()
{
using namespace std::chrono_literals;
// initialize the zmq context with a single IO thread
zmq::context_t context{1};
// construct a REP (reply) socket and bind to interface
zmq::socket_t socket{context, zmq::socket_type::rep};
socket.bind("tcp://*:5555");
// prepare some static data for responses
const std::string data{"World"};
for (;;)
{
zmq::message_t request;
// receive a request from client
socket.recv(request, zmq::recv_flags::none);
std::cout << "Received " << request.to_string() << std::endl;
// simulate work
std::this_thread::sleep_for(1s);
// send the reply to the client
socket.send(zmq::buffer(data), zmq::send_flags::none);
}
return 0;
}
编译
g++ -o server server.cpp `pkg-config --cflags --libs libzmq`
g++ -o client client.cpp `pkg-config --cflags --libs libzmq`
请求应答步骤
请求端
建立与应答端的连接
第一步:创建ZMQ上下文
context_t context{1};
创建一个 ZeroMQ 上下文(context),并初始化为只有一个 I/O 线程。context_t 是 ZeroMQ 库中用于管理套接字的类。
第二步:创建一个请求套接字
socket_t socket{context, socket_type::req}
在上下文中创建一个套接字(socket),并指定其类型为 req(请求者)。这意味着这个套接字将发送请求并等待响应。
第三步:连接端点
socket.connect("tcp://localhost:5555");
将套接字连接到本地主机上的 5555 端口。这是服务器监听的端口。
发送消息请求
发送消息不是固定的,可以用静态字符串发送,也可以输入信息发送,但用socket发送消息的函数是不变的。
socket.send()
用于发送消息
socket.send(buffer(data), send_flags::none);
函数参数
buffer(data)
这是一个 zmq::buffer 对象,它是一个辅助类,用于创建一个消息缓冲区。在这里,它接收一个 std::string 类型的参数 data,并将这个字符串的内容作为消息发送。buffer 类型的对象通常用于封装消息数据,以便与 ZeroMQ 的套接字接口一起使用。
send_flags
这是一个枚举值,用于指定发送消息时的选项。send_flags::none 表示没有特殊的发送标志,即消息将按照默认的方式发送。ZeroMQ 还提供了其他发送标志,例如:
send_flags::dontwait:非阻塞发送,如果无法立即发送消息,函数会立即返回,而不是等待。
send_flags::sndmore:表示消息分多部分发送,这个标志用于告诉 ZeroMQ 还有更多的消息部分即将发送。
函数返回值
在 ZeroMQ 的 C++ 绑定中,socket.send() 函数的返回值是一个整数,表示发送的字节数。这个返回值通常用于确认消息是否成功发送,以及发送了多少数据。
如果发送成功,函数返回发送的字节数。如果发送失败,函数返回 -1,并设置相应的错误代码,可以通过 errno 来获取。
接收应答端的回复
message_t
这个message_t也是ZMQ库中的类,reply也就是类的对象
message_t reply{};
创建一个 message_t 类型的变量 reply,用于接收服务器的响应。
socket.recv();
socket.recv(reply, recv_flags::none);
从服务器接收响应消息,并将消息内容存储在 reply 变量中。
函数参数
reply
这是一个 zmq::message_t 类型的对象,它用于存储从套接字接收到的消息。zmq::message_t 是 ZeroMQ 库中用于表示消息的类。当 recv 函数成功执行后,reply 对象将包含接收到的消息数据。
recv_flags::none:
这是一个枚举值,用于指定接收消息时的选项。recv_flags::none 表示没有特殊的接收标志,即消息将按照默认的方式接收。ZeroMQ 还提供了其他接收标志,例如:
recv_flags::dontwait:非阻塞接收,如果当前没有消息可接收,函数会立即返回,而不是等待。
recv_flags::recvmore:告诉 ZeroMQ 预期更多的消息部分将会到来。这通常用于多部分消息的接收。
函数返回值
在 ZeroMQ 的 C++ 绑定中,socket.recv() 函数的返回值是一个布尔值,表示是否成功接收到了消息。这个返回值用于判断接收操作是否成功完成。
如果返回 true,表示成功接收到了消息,并且 zmq::message_t 对象(如示例中的 reply)中包含了接收到的消息数据。
如果返回 false,表示接收操作失败。失败的原因可能是因为套接字被关闭、发生了错误,或者(如果使用了非阻塞标志)没有消息可接收。
应答端
建立与端点的连接
第一步:创建ZMQ上下文
context_t context{1};
创建一个 ZeroMQ 上下文(context),并初始化为只有一个 I/O 线程。context_t 是 ZeroMQ 库中用于管理套接字的类。
第二步:创建一个请求套接字
socket_t socket{context, socket_type::rep};
在上下文中创建一个套接字(socket),并指定其类型为 rep(应答者)。这意味着这个套接字将等待请求消息并响应回复。
第三步:连接端点
socket.bind("tcp://*:5555");
将套接字连接到本地主机上的 5555 端口。这是服务器的端口。
接收请求端的请求消息
message_t
这个message_t也是ZMQ库中的类,reply也就是类的对象
message_t request;
创建一个 message_t 类型的变量 request,用于接收请求端的消息。
socket.recv();
socket.recv(request, recv_flags::none);
从服务器接收响应消息,并将消息内容存储在 request变量中。
处理请求消息,应答请求
socket.send()
用于发送消息
socket.send(buffer(data), send_flags::none);