From 99ea8d16469042625d242b00a31ab02686215b55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B9=20=D0=9C=D0=B0=D1=80?= =?UTF-8?q?=D0=B8=D0=BD=D0=BA=D0=B5=D0=B2=D0=B8=D1=87?= Date: Tue, 2 Dec 2025 17:08:39 +0700 Subject: [PATCH] impove ipc --- src/rpc/IpcMessage.h | 58 ++++++++++++++++++++++++++++------------- src/rpc/IpcPipeChannel.h | 16 +++++------- src/rpc/RpcChannel.h | 7 +++-- src/rpc/RpcClient.h | 13 +++------ src/rpc/RpcInvoker.h | 34 ++++++++++++------------ src/server.cpp | 4 +-- tools/templates/skeleton.cpp.j2 | 2 +- tools/templates/skeleton.h.j2 | 4 +-- 8 files changed, 75 insertions(+), 63 deletions(-) diff --git a/src/rpc/IpcMessage.h b/src/rpc/IpcMessage.h index b4bcd5d..f1c3b70 100644 --- a/src/rpc/IpcMessage.h +++ b/src/rpc/IpcMessage.h @@ -3,38 +3,60 @@ #include #include -// Примитивный IPC‑формат сообщений: -// комбинация std::ostringstream / std::istringstream с удобным API add/read. +// Примитивное IPC‑сообщение с API add() / get(). +// Под капотом пока текстовый формат, но снаружи интерфейс не завязан на std::string. -class IpcMessageWriter { +class IpcMessage { public: + IpcMessage() = default; + + explicit IpcMessage(const std::string& raw) + : raw_(raw) {} + + IpcMessage(const IpcMessage& other) + : raw_(other.raw_) {} + + IpcMessage& operator=(const IpcMessage& other) { + if (this != &other) { + raw_ = other.raw_; + in_.clear(); + in_initialized_ = false; + out_.str(std::string{}); + } + return *this; + } + + // Конструирование исходящего сообщения. template void add(const T& v) { out_ << v << ' '; + raw_ = out_.str(); } - std::string str() const { - return out_.str(); - } - -private: - std::ostringstream out_; -}; - -class IpcMessageReader { -public: - explicit IpcMessageReader(const std::string& data) - : in_(data) {} - + // Чтение входящего сообщения по частям. template - T read() { + T get() { + if (!in_initialized_) { + in_.str(raw_); + in_initialized_ = true; + } T v{}; in_ >> v; return v; } + const std::string& raw() const { + return raw_; + } + + bool empty() const { + return raw_.empty(); + } + private: + std::string raw_; + std::ostringstream out_; std::istringstream in_; + bool in_initialized_{false}; }; - diff --git a/src/rpc/IpcPipeChannel.h b/src/rpc/IpcPipeChannel.h index 19f936d..0d4f17e 100644 --- a/src/rpc/IpcPipeChannel.h +++ b/src/rpc/IpcPipeChannel.h @@ -6,10 +6,8 @@ #include #include -#include - // IPC‑канал поверх именованных pipe. -// Инкапсулирует работу с файловыми дескрипторами и обмен строковыми сообщениями. +// Инкапсулирует работу с файловыми дескрипторами и обмен сообщениями IpcMessage. class IpcPipeChannel : public RpcChannel { public: @@ -28,25 +26,26 @@ public: } } - void send(const std::string& data) override { + void send(const IpcMessage& msg) override { if (fdOut_ < 0) { return; } + const std::string& data = msg.raw(); ::write(fdOut_, data.c_str(), data.size()); ::write(fdOut_, "\n", 1); } - std::string receive() override { + IpcMessage receive() override { if (fdIn_ < 0) { - return {}; + return IpcMessage{}; } char buf[4096]; const int n = ::read(fdIn_, buf, sizeof(buf) - 1); if (n <= 0) { - return {}; + return IpcMessage{}; } buf[n] = 0; - return std::string(buf); + return IpcMessage(std::string(buf)); } private: @@ -54,4 +53,3 @@ private: int fdOut_{-1}; }; - diff --git a/src/rpc/RpcChannel.h b/src/rpc/RpcChannel.h index 011198c..4a05015 100644 --- a/src/rpc/RpcChannel.h +++ b/src/rpc/RpcChannel.h @@ -1,11 +1,10 @@ #pragma once -#include -#include +#include "IpcMessage.h" class RpcChannel { public: virtual ~RpcChannel() = default; - virtual void send(const std::string& data) = 0; - virtual std::string receive() = 0; + virtual void send(const IpcMessage& msg) = 0; + virtual IpcMessage receive() = 0; }; diff --git a/src/rpc/RpcClient.h b/src/rpc/RpcClient.h index 0f657a0..31ce775 100644 --- a/src/rpc/RpcClient.h +++ b/src/rpc/RpcClient.h @@ -1,9 +1,6 @@ #pragma once #include "RpcChannel.h" -#include "IpcMessage.h" - -#include class RpcClient { public: @@ -11,7 +8,7 @@ public: template Ret call(const std::string& method, const Args&... args) { - IpcMessageWriter msg; + IpcMessage msg; // имя метода msg.add(method); @@ -20,13 +17,11 @@ public: (msg.add(args), ...); // отправить - channel.send(msg.str()); + channel.send(msg); // получить ответ - std::string resp = channel.receive(); - IpcMessageReader reader(resp); - - return reader.template read(); + IpcMessage resp = channel.receive(); + return resp.template get(); } private: diff --git a/src/rpc/RpcInvoker.h b/src/rpc/RpcInvoker.h index 3511eb2..27e4e47 100644 --- a/src/rpc/RpcInvoker.h +++ b/src/rpc/RpcInvoker.h @@ -14,24 +14,24 @@ public: const std::string& name, Ret (Obj::*method)(Args...)) { handlers[name] = - [instance, method](const std::string& req) -> std::string { - IpcMessageReader reader(req); + [instance, method](const IpcMessage& req) -> IpcMessage { + IpcMessage msg = req; // пропустить имя метода - (void)reader.template read(); + (void)msg.template get(); // читать аргументы и вызвать метод - return callMethod(instance, method, reader); + return callMethod(instance, method, msg); }; } - std::string dispatch(const std::string& request) { - IpcMessageReader reader(request); - const std::string method = reader.read(); + IpcMessage dispatch(const IpcMessage& request) { + IpcMessage tmp = request; + const std::string method = tmp.get(); auto it = handlers.find(method); if (it == handlers.end()) { - return "ERR"; + return IpcMessage{}; } return it->second(request); @@ -39,25 +39,25 @@ public: private: template - static std::string callMethod(Obj* obj, - Ret (Obj::*method)(Args...), - IpcMessageReader& reader) { - auto tuple = readArgs(reader); + static IpcMessage callMethod(Obj* obj, + Ret (Obj::*method)(Args...), + IpcMessage& msg) { + auto tuple = readArgs(msg); Ret result = std::apply(method, std::tuple_cat(std::make_tuple(obj), tuple)); - IpcMessageWriter out; + IpcMessage out; out.add(result); - return out.str(); + return out; } template - static std::tuple readArgs(IpcMessageReader& reader) { - return std::tuple{reader.template read()...}; + static std::tuple readArgs(IpcMessage& msg) { + return std::tuple{msg.template get()...}; } std::unordered_map> + std::function> handlers; }; diff --git a/src/server.cpp b/src/server.cpp index f216047..6884dc6 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -18,11 +18,11 @@ int main() { MyServiceSkeleton skeleton(realObj); while (true) { - std::string req = ch.receive(); + IpcMessage req = ch.receive(); if (req.empty()) { break; } - std::string resp = skeleton.dispatch(req); + IpcMessage resp = skeleton.dispatch(req); ch.send(resp); } } diff --git a/tools/templates/skeleton.cpp.j2 b/tools/templates/skeleton.cpp.j2 index d45e928..c402f46 100644 --- a/tools/templates/skeleton.cpp.j2 +++ b/tools/templates/skeleton.cpp.j2 @@ -9,7 +9,7 @@ {% endfor %} } -std::string {{ cls.name }}Skeleton::dispatch(const std::string& req) { +IpcMessage {{ cls.name }}Skeleton::dispatch(const IpcMessage& req) { return invoker.dispatch(req); } diff --git a/tools/templates/skeleton.h.j2 b/tools/templates/skeleton.h.j2 index 619f350..1cbc3c5 100644 --- a/tools/templates/skeleton.h.j2 +++ b/tools/templates/skeleton.h.j2 @@ -3,13 +3,11 @@ #include "{{ cls.name }}.h" #include "rpc/RpcInvoker.h" -#include - class {{ cls.name }}Skeleton { public: explicit {{ cls.name }}Skeleton({{ cls.name }}& obj); - std::string dispatch(const std::string& req); + IpcMessage dispatch(const IpcMessage& req); private: RpcInvoker invoker;