Zmq.rs + tokio network interface implementation

⚓ Rust    📅 2026-01-18    👤 surdeus    👁️ 4      

surdeus

Hello!

I'm currently learning tokio library and to practice a bit I'm implementing a ZeroMQ+Protobuf application for a custom project. This is the list of dependencies I'm using:

prost = "0.14.1"
prost-types = "0.14.1"
tokio = { version = "1.48.0", features = ["full"] }
tokio-stream = { version = "0.1.17", features = ["full"] }
tokio-util = { version = "0.7.17", features = ["full"] }
tracing = "0.1.43"
tracing-subscriber = "0.3.22"
# pre-release version of ZeroMQ
zeromq = { git = "https://github.com/zeromq/zmq.rs", rev = "4006664971ece1b7c44f20ef8b2d0ae97eca18d4" }

This is a simplified implementation of a router interface I wrote: Rust Playground. Here are some notes about implementation:

The main characteristic of this interface is that it is completely asynchronous, meaning send and receive are completely decoupled. This is a requirement of the current project I'm working on. You can have a classic request-response message pattern but this is implemented in the application layer. I have simplified many things to keep the example code small, so ignore random unwraps and InterfaceError being a static string.

I tried to encapsulate all the logic in a single struct, but the main_loop task requires the socket to be moved so I came up with the bind_and_start function and RouterHandle, which I don't really like but it's the only solution I could find with my limited knowledge. I would appreciate any suggestion on how to improve this design.

I don't really understand why the compiler requires the generic parameter P to have 'static lifetime in the implementation block.

In the main loop, the only way I could find to send and receive in the same scope is to use tokio::select! (remember I cannot move the socket around so I couldn't split send and receive in different tasks). I had to put biased because with high request rate to the interface, the zmq recv would basically prevent other branches to be selected. I'm not entirely sure if zmq.rs socket is cancellation safe, but so far I never had issue of missing messages.

Also, If you know of some good tokio implementation (not just basic send->receive examples) that could help better understand and improve my code, please share!

Thanks in advance.

2 posts - 2 participants

Read full topic

🏷️ Rust_feed