diff --git a/client-cpp/meson.build b/client-cpp/meson.build
new file mode 100644
index 0000000000000000000000000000000000000000..5fa482df79d4dac2517214e7814b8a161678c856
--- /dev/null
+++ b/client-cpp/meson.build
@@ -0,0 +1,23 @@
+project('client-cpp', 'cpp',
+  version: '0.1.0',
+  license: 'MIT',
+  default_options: ['cpp_std=c++17']
+)
+
+# Dependencies
+libzmq_dep = dependency('libzmq')
+protocol_dep = dependency('protocol')
+
+deps = [
+  libzmq_dep,
+  protocol_dep
+]
+
+client_cpp = executable('client-cpp', [
+    'src/main.cpp',
+    'src/misc.cpp', 'src/misc.hpp'
+  ],
+  include_directories: 'src',
+  dependencies: deps,
+  install: true
+)
diff --git a/client-cpp/src/main.cpp b/client-cpp/src/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ea014fe2760ca76be45e3daf3d6cff6851f7798b
--- /dev/null
+++ b/client-cpp/src/main.cpp
@@ -0,0 +1,7 @@
+#include "misc.hpp"
+
+int main()
+{
+    client_main_loop();
+    return 0;
+}
diff --git a/client-cpp/src/misc.cpp b/client-cpp/src/misc.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..891724afe7c238805bb7e6d939e92aa9eb95177a
--- /dev/null
+++ b/client-cpp/src/misc.cpp
@@ -0,0 +1,60 @@
+#include "misc.hpp"
+
+#include <zmq.h>
+
+#include <protocol/hello.pb.h>
+
+void client_main_loop(void)
+{
+    auto context = zmq_ctx_new();
+    assert(context != nullptr);
+
+    auto socket = zmq_socket(context, ZMQ_REP);
+    assert(socket != nullptr);
+
+    int rc = zmq_bind(socket, "tcp://*:28000");
+    assert(rc == 0);
+
+    zmq_msg_t msg;
+    hello::Order order;
+    std::string msg_buffer_str;
+
+    // Round 1: hello
+    zmq_msg_init(&msg);
+    if (zmq_msg_recv(&msg, socket, 0) == -1)
+        throw std::runtime_error(std::string("cannot read message on socket (errno=") + strerror(errno) + ")");
+    zmq_msg_close(&msg);
+
+    order.mutable_hello()->set_name("client-cpp");
+    order.SerializeToString(&msg_buffer_str);
+
+    if (zmq_send(socket, msg_buffer_str.data(), msg_buffer_str.size(), 0) == -1)
+        throw std::runtime_error(std::string("cannot send message on socket (errno=") + strerror(errno) + ")");
+
+    // Round 2: compute flops
+    zmq_msg_init(&msg);
+    if (zmq_msg_recv(&msg, socket, 0) == -1)
+        throw std::runtime_error(std::string("cannot read message on socket (errno=") + strerror(errno) + ")");
+    zmq_msg_close(&msg);
+
+    order.mutable_compute_flops()->set_flop_amount(1e9);
+    order.SerializeToString(&msg_buffer_str);
+
+    if (zmq_send(socket, msg_buffer_str.data(), msg_buffer_str.size(), 0) == -1)
+        throw std::runtime_error(std::string("cannot send message on socket (errno=") + strerror(errno) + ")");
+
+    // Round 3: bye
+    zmq_msg_init(&msg);
+    if (zmq_msg_recv(&msg, socket, 0) == -1)
+        throw std::runtime_error(std::string("cannot read message on socket (errno=") + strerror(errno) + ")");
+    zmq_msg_close(&msg);
+
+    order.mutable_bye();
+    order.SerializeToString(&msg_buffer_str);
+
+    if (zmq_send(socket, msg_buffer_str.data(), msg_buffer_str.size(), 0) == -1)
+        throw std::runtime_error(std::string("cannot send message on socket (errno=") + strerror(errno) + ")");
+
+    zmq_close(socket);
+    zmq_ctx_destroy(context);
+}
diff --git a/client-cpp/src/misc.hpp b/client-cpp/src/misc.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..a0fe1a3a57f32f6872bcc6612b6b88c7f25327d6
--- /dev/null
+++ b/client-cpp/src/misc.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+void client_main_loop(void);
diff --git a/default.nix b/default.nix
index 9ff0dfd2e7cb2221328b0bb6bbda2cc0d27ee520..6a5ee5753b59b2b455afe8f1bb1e9137141f3127 100644
--- a/default.nix
+++ b/default.nix
@@ -58,6 +58,23 @@ let self = rec {
       zeromq
     ];
   };
+  client-cpp = pkgs.stdenv.mkDerivation {
+    pname = "client-cpp";
+    version = "local";
+    src = pkgs.lib.sourceByRegex ./client-cpp [
+      "meson\.build"
+      "src"
+      "src/.*\.cpp"
+      "src/.*\.hpp"
+    ];
+    buildInputs = with pkgs; [
+      protocol-cpp
+      meson
+      pkg-config
+      ninja
+      zeromq
+    ];
+  };
 };
 in
   self