ZMQ [java]
java中ZMQ的用法
简介
ZMQ是基于C语言实现的消息队列, 可用TCP或UDP实现. JeroMQ是其java实现, 首先导入maven:
<!-- https://mvnrepository.com/artifact/org.zeromq/jeromq -->
<dependency>
<groupId>org.zeromq</groupId>
<artifactId>jeromq</artifactId>
<version>0.5.3</version>
</dependency>
使用
请求-响应模式
该模式由客户端和服务端组成, 必须是问了再答, 答了再问
- 客户端: 发送 -> 接收 --> 发送 --> ...
- 服务端: 接收 --> 发送 --> 接收 --> ...
服务端
服务端监听8888的tcp连接
public class Response {
public static void main(String args[]) throws InterruptedException {
ZMQ.Context context = ZMQ.context(1); //I/O线程上下文的数量为1
ZMQ.Socket socket = context.socket(ZMQ.REP); //ZMQ.REP表示这是一个reponse类型的socket
socket.bind("tcp://*:8888"); //绑定到8888端口
while (true) {
byte[] request = socket.recv();
if (new String(request).equals("END"))
break;
System.out.println("Response recv:\t" + new String(request));
String response = "I got it";
Thread.sleep(3000);
socket.send(response.getBytes());
}
//关闭
socket.close();
context.term();
}
}
客户端
public class Request {
public static void main(String args[]) {
ZMQ.Context context = ZMQ.context(1); //I/O线程上下文的数量为1
ZMQ.Socket socket = context.socket(ZMQ.REQ); //ZMQ.REQ表示这是一个request类型的socket
socket.connect("tcp://127.0.0.1:8888"); //连接到8888端口
for (int i = 0; i < 10; i++) {
long now = System.currentTimeMillis();
String request = "hello, time is " + now;
socket.send(request.getBytes());
byte[] response = socket.recv();
System.out.println("Request recv:\t" + new String(response));
}
socket.send("END".getBytes());
//关闭
socket.close();
context.term();
}
}
发布-订阅模式
该服务器一直发, 客户端订阅后就可以接受服务器消息了.
服务端(发布者)
服务端只需发送以Time和Order开头的消息
public class Server {
public static void main(String[] args) {
try (ZContext context = new ZContext()) {
ZMQ.Socket publisher = context.createSocket(ZMQ.PUB); //publish类型
publisher.bind("tcp://*:5555");
Random random = new Random();
while (true) {
String update;
//随机将update赋值为Time: 或Order: 开头的值
if (random.nextInt(10) <= 5)
update = "Time: " + System.currentTimeMillis();
else
update = "Order: " + System.currentTimeMillis();
publisher.send(update); //发送
System.out.println("SEND:[" + update + "]");
}
}
}
}
客户端(订阅者)
客户端只订阅以Time开头的
public class Client {
public static void main(String args[]) {
try (ZContext context = new ZContext()) {
ZMQ.Socket subscriber = context.createSocket(ZMQ.SUB); //subscribe类型
subscriber.connect("tcp://localhost:5555");
subscriber.subscribe("Time:".getBytes()); //只订阅Time: 开头的信息
for (int i = 0; i < 1000; i++) {
System.out.println(subscriber.recvStr()); //recvStr直接返回String,内部调用了recv,将byte数组转化为String
}
}
}
}
router/dealer模式
Router和Dealer搭配使用时,必须都需要设置router id。发送给Router或Dealer的消息模型如下:
- Router接收的消息模型:
[router_id][空帧][数据帧]
- Router发送的消息模型:
[router_id][空帧][数据帧]
- Router发送到网络上的数据:
[router_id][数据帧]
- Dealer接收的消息模型:
[数据帧]
- Dealer发送的消息模型:
[空帧][数据帧]
Dealer就像是一个异步的REQ,而Router就像一个异步的REP。所以可以相互使用。Router做代理可以提供可靠的模式来分别识别客户端和后端服务器
import org.zeromq.SocketType;
import org.zeromq.ZContext;
import org.zeromq.ZMQ;
public class Client {
public static void main(String[] args) {
try (ZContext context = new ZContext()) {
// 创建ROUTER套接字作为服务端
// 创建DEALER套接字作为客户端
ZMQ.Socket client = context.createSocket(SocketType.DEALER);
// 连接到服务端
client.connect("tcp://localhost:5560");
// 客户端发送多个请求
client.setIdentity(new String("wang").getBytes());
for (int i = 0; i < 3; i++) {
client.send("Hello " + i);
}
while (true) {
String message = client.recvStr();
if (message == null) {
continue;
}
System.out.println("Received: " + message);
}
}
}
}
import org.zeromq.SocketType;
import org.zeromq.ZContext;
import org.zeromq.ZMQ;
import org.zeromq.ZMsg;
public class Server {
public static void main(String[] args) {
try (ZContext context = new ZContext()) {
// 创建ROUTER套接字作为服务端
ZMQ.Socket server = context.createSocket(SocketType.ROUTER);
// 绑定到端口5560
server.bind("tcp://*:5560");
// 服务端接收请求并发送回复
int i = 0;
server.setIdentity(new String("wang").getBytes());
while (true) {
ZMsg zMsg = ZMsg.recvMsg(server);
if (zMsg == null) {
continue;
}
System.out.println("recv: " + zMsg);
ZMsg zMsg1 = new ZMsg();
zMsg1.add(new String("wang").getBytes());
zMsg1.add("abc " + i++);
zMsg1.send(server);
}
}
}
}
recv: [ wang, Hello 0 ]
recv: [ wang, Hello 1 ]
recv: [ wang, Hello 2 ]
=================================
Received: abc 0
Received: abc 1
Received: abc 2
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?