Skip to content

Commit ba74440

Browse files
committed
add example for protobuf and zeromq
1 parent 506e15f commit ba74440

8 files changed

Lines changed: 150 additions & 1 deletion

File tree

.github/workflows/build_cmake.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ jobs:
6565
# We need to source the profile file to make sure conan is in PATH
6666
run: |
6767
source ~/.profile
68-
cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCPP_STARTER_USE_SML=ON -DCPP_STARTER_USE_BOOST_BEAST=ON -DCPP_STARTER_USE_CROW=ON
68+
cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCPP_STARTER_USE_SML=ON -DCPP_STARTER_USE_BOOST_BEAST=ON -DCPP_STARTER_USE_CROW=ON -DCPP_STARTER_USE_CPPZMQ_PROTO=ON
6969
7070
- name: Build
7171
working-directory: ${{runner.workspace}}/build

cmake/Conan.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ macro(run_conan)
1919
nlohmann_json/3.10.5
2020
boost/1.78.0
2121
crowcpp-crow/1.0+1
22+
cppzmq/4.8.1
23+
protobuf/3.20.0
2224
OPTIONS
2325
${CONAN_EXTRA_OPTIONS}
2426
gtest:build_gmock=True

src/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
OPTION(CPP_STARTER_USE_SML "Enable compilation of SML sample" OFF)
22
OPTION(CPP_STARTER_USE_BOOST_BEAST "Enable compilation of boost beast sample" OFF)
33
OPTION(CPP_STARTER_USE_CROW "Enable compilation of crow sample" OFF)
4+
OPTION(CPP_STARTER_USE_CPPZMQ_PROTO "Enable compilation of protobuf and cppzmq sample" OFF)
45

56
# SML
67
IF(CPP_STARTER_USE_SML)
@@ -20,6 +21,11 @@ IF(CPP_STARTER_USE_CROW)
2021
ADD_SUBDIRECTORY(crow)
2122
ENDIF()
2223

24+
# CPPZMQ & Protobuf
25+
IF(CPP_STARTER_USE_CPPZMQ_PROTO)
26+
MESSAGE("Using CPPZMQ & Protobuf")
27+
ADD_SUBDIRECTORY(protobuf.cppzmq)
28+
ENDIF()
2329

2430
# Generic test that uses conan libs
2531
ADD_EXECUTABLE(intro main.cpp)

src/protobuf.cppzmq/CMakeLists.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
FIND_PACKAGE(Protobuf REQUIRED)
2+
3+
INCLUDE_DIRECTORIES(${Protobuf_INCLUDE_DIRS})
4+
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
5+
6+
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${PROTO_SRC_DIR} proto/event.proto)
7+
8+
ADD_EXECUTABLE(test_cppzmq_proto_server server/main.cpp ${PROTO_SRCS} ${PROTO_HDRS})
9+
ADD_EXECUTABLE(test_cppzmq_proto_client client/main.cpp ${PROTO_SRCS} ${PROTO_HDRS})
10+
11+
TARGET_INCLUDE_DIRECTORIES(test_cppzmq_proto_server PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/common)
12+
TARGET_INCLUDE_DIRECTORIES(test_cppzmq_proto_client PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/common)
13+
14+
TARGET_LINK_LIBRARIES(test_cppzmq_proto_server PRIVATE CONAN_PKG::spdlog CONAN_PKG::cppzmq CONAN_PKG::protobuf CONAN_PKG::spdlog)
15+
TARGET_LINK_LIBRARIES(test_cppzmq_proto_client PRIVATE CONAN_PKG::spdlog CONAN_PKG::cppzmq CONAN_PKG::protobuf CONAN_PKG::spdlog)
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#include "event.pb.h"
2+
#include <spdlog/spdlog.h>
3+
#include <string>
4+
#include <zmq.hpp>
5+
#include <include/common.h>
6+
7+
int main()
8+
{
9+
// initialize the zmq context with a single IO thread
10+
zmq::context_t context{ 1 };
11+
12+
// construct a REQ (request) socket and connect to interface
13+
zmq::socket_t socket{ context, zmq::socket_type::req };
14+
socket.connect("tcp://localhost:5555");
15+
16+
// set up some static data to send
17+
const std::string senderName{ "Client" };
18+
int32_t pingCount = 0;
19+
int32_t pongCount = 0;
20+
21+
for (;;) {
22+
// send the request message
23+
own::proto::Event event;
24+
event.set_sender(senderName);
25+
event.set_action(own::proto::Event::PONG);
26+
event.set_ping_count(pingCount);
27+
event.set_pong_count(pongCount);
28+
29+
std::string data;
30+
event.SerializeToString(&data);
31+
32+
// send to the server
33+
socket.send(zmq::buffer(data), zmq::send_flags::none);
34+
35+
// wait for reply from server
36+
zmq::message_t reply{};
37+
socket.recv(reply, zmq::recv_flags::none);
38+
39+
own::proto::Event receivedEvent;
40+
receivedEvent.ParseFromArray(reply.data(), static_cast<int>(reply.size()));
41+
pingCount = receivedEvent.ping_count();
42+
pongCount = receivedEvent.pong_count() + 1;
43+
44+
spdlog::info("Received from: {} Action: {} Ping count: {} Pong count: {}",
45+
receivedEvent.sender(),
46+
own::proto::Event_PingPong_Name(receivedEvent.action()),
47+
receivedEvent.ping_count(),
48+
receivedEvent.pong_count());
49+
50+
if (receivedEvent.pong_count() == Common::maxCount) { break; }
51+
}
52+
53+
return 0;
54+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
namespace Common {
2+
constexpr auto maxCount = 10;
3+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
syntax = "proto3";
2+
3+
package own.proto;
4+
5+
6+
message Event {
7+
string sender = 1;
8+
enum PingPong {
9+
PING = 0;
10+
PONG = 1;
11+
}
12+
PingPong action = 2;
13+
int32 ping_count = 3;
14+
int32 pong_count = 4;
15+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#include "event.pb.h"
2+
#include <chrono>
3+
#include <include/common.h>
4+
#include <spdlog/spdlog.h>
5+
#include <thread>
6+
#include <zmq.hpp>
7+
8+
int main()
9+
{
10+
using namespace std::chrono_literals;
11+
12+
// initialize the zmq context with a single IO thread
13+
zmq::context_t context{ 1 };
14+
15+
// construct a REP (reply) socket and bind to interface
16+
zmq::socket_t socket{ context, zmq::socket_type::rep };
17+
socket.bind("tcp://*:5555");
18+
19+
// prepare some static data for responses
20+
const std::string senderName{ "Server" };
21+
22+
for (;;) {
23+
zmq::message_t request;
24+
25+
// receive a request from client
26+
socket.recv(request, zmq::recv_flags::none);
27+
own::proto::Event receivedEvent;
28+
receivedEvent.ParseFromArray(request.data(), static_cast<int>(request.size()));
29+
30+
// simulate work
31+
std::this_thread::sleep_for(500ms);
32+
own::proto::Event event;
33+
event.set_sender(senderName);
34+
event.set_action(own::proto::Event::PING);
35+
event.set_ping_count(receivedEvent.ping_count() + 1);
36+
event.set_pong_count(receivedEvent.pong_count());
37+
38+
std::string data;
39+
event.SerializeToString(&data);
40+
41+
// send the reply to the client
42+
socket.send(zmq::buffer(data), zmq::send_flags::none);
43+
44+
spdlog::info("Received from: {} Action: {} Ping count: {} Pong count: {}",
45+
receivedEvent.sender(),
46+
own::proto::Event_PingPong_Name(receivedEvent.action()),
47+
receivedEvent.ping_count(),
48+
receivedEvent.pong_count());
49+
50+
if (receivedEvent.ping_count() == Common::maxCount) { break; }
51+
}
52+
53+
return 0;
54+
}

0 commit comments

Comments
 (0)