diff --git a/src/client.cpp b/src/client.cpp index 2c354ac..89ba30e 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1,48 +1,21 @@ #include "MyService.proxy.h" -#include "rpc/RpcChannel.h" +#include "rpc/IpcPipeChannel.h" -#include #include -#include #include -#include - -class RpcChannelFifoClient : public RpcChannel { -public: - RpcChannelFifoClient(const char* inPipe, const char* outPipe) { - fdOut = open(inPipe, O_WRONLY); - fdIn = open(outPipe, O_RDONLY); - } - - void send(const std::string& data) override { - ::write(fdOut, data.c_str(), data.size()); - ::write(fdOut, "\n", 1); - } - - std::string receive() override { - char buf[4096]; - int n = ::read(fdIn, buf, sizeof(buf) - 1); - if (n <= 0) { - return {}; - } - buf[n] = 0; - return std::string(buf); - } - -private: - int fdIn{}; - int fdOut{}; -}; int main() { + // Создание FIFO — часть пользовательского IPC‑кода. mkfifo("/tmp/rpc_in", 0666); mkfifo("/tmp/rpc_out", 0666); - RpcChannelFifoClient ch("/tmp/rpc_in", "/tmp/rpc_out"); + // IPC‑уровень: канал поверх pipe. + IpcPipeChannel ch("/tmp/rpc_in", "/tmp/rpc_out"); + + // RPC‑уровень: прокси поверх канала. MyServiceProxy proxy(ch); int r = proxy.add(7, 8); std::cout << "RESULT: " << r << std::endl; } - diff --git a/src/rpc/IpcMessage.h b/src/rpc/IpcMessage.h new file mode 100644 index 0000000..b4bcd5d --- /dev/null +++ b/src/rpc/IpcMessage.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include + +// Примитивный IPC‑формат сообщений: +// комбинация std::ostringstream / std::istringstream с удобным API add/read. + +class IpcMessageWriter { +public: + template + void add(const T& v) { + out_ << v << ' '; + } + + 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 v{}; + in_ >> v; + return v; + } + +private: + std::istringstream in_; +}; + + diff --git a/src/rpc/IpcPipeChannel.h b/src/rpc/IpcPipeChannel.h new file mode 100644 index 0000000..19f936d --- /dev/null +++ b/src/rpc/IpcPipeChannel.h @@ -0,0 +1,57 @@ +#pragma once + +#include "RpcChannel.h" + +#include +#include +#include + +#include + +// IPC‑канал поверх именованных pipe. +// Инкапсулирует работу с файловыми дескрипторами и обмен строковыми сообщениями. + +class IpcPipeChannel : public RpcChannel { +public: + IpcPipeChannel(const char* writePipe, const char* readPipe) { + // Канал не создаёт FIFO, только открывает. + fdOut_ = ::open(writePipe, O_WRONLY); + fdIn_ = ::open(readPipe, O_RDONLY); + } + + ~IpcPipeChannel() override { + if (fdIn_ >= 0) { + ::close(fdIn_); + } + if (fdOut_ >= 0) { + ::close(fdOut_); + } + } + + void send(const std::string& data) override { + if (fdOut_ < 0) { + return; + } + ::write(fdOut_, data.c_str(), data.size()); + ::write(fdOut_, "\n", 1); + } + + std::string receive() override { + if (fdIn_ < 0) { + return {}; + } + char buf[4096]; + const int n = ::read(fdIn_, buf, sizeof(buf) - 1); + if (n <= 0) { + return {}; + } + buf[n] = 0; + return std::string(buf); + } + +private: + int fdIn_{-1}; + int fdOut_{-1}; +}; + + diff --git a/src/rpc/RpcClient.h b/src/rpc/RpcClient.h index d6c1f15..0f657a0 100644 --- a/src/rpc/RpcClient.h +++ b/src/rpc/RpcClient.h @@ -1,9 +1,8 @@ #pragma once #include "RpcChannel.h" -#include "RpcSerializer.h" +#include "IpcMessage.h" -#include #include class RpcClient { @@ -12,22 +11,22 @@ public: template Ret call(const std::string& method, const Args&... args) { - std::ostringstream out; + IpcMessageWriter msg; // имя метода - RpcSerializer::write(out, method); + msg.add(method); // аргументы - (RpcSerializer::write(out, args), ...); + (msg.add(args), ...); // отправить - channel.send(out.str()); + channel.send(msg.str()); // получить ответ std::string resp = channel.receive(); - std::istringstream in(resp); + IpcMessageReader reader(resp); - return RpcSerializer::read(in); + return reader.template read(); } private: diff --git a/src/rpc/RpcInvoker.h b/src/rpc/RpcInvoker.h index b963db3..3511eb2 100644 --- a/src/rpc/RpcInvoker.h +++ b/src/rpc/RpcInvoker.h @@ -1,9 +1,8 @@ #pragma once -#include "RpcSerializer.h" +#include "IpcMessage.h" #include -#include #include #include #include @@ -16,21 +15,19 @@ public: Ret (Obj::*method)(Args...)) { handlers[name] = [instance, method](const std::string& req) -> std::string { - std::istringstream in(req); + IpcMessageReader reader(req); // пропустить имя метода - std::string skip; - in >> skip; + (void)reader.template read(); // читать аргументы и вызвать метод - return callMethod(instance, method, in); + return callMethod(instance, method, reader); }; } std::string dispatch(const std::string& request) { - std::istringstream in(request); - std::string method; - in >> method; + IpcMessageReader reader(request); + const std::string method = reader.read(); auto it = handlers.find(method); if (it == handlers.end()) { @@ -44,19 +41,19 @@ private: template static std::string callMethod(Obj* obj, Ret (Obj::*method)(Args...), - std::istringstream& in) { - auto tuple = readArgs(in); + IpcMessageReader& reader) { + auto tuple = readArgs(reader); Ret result = std::apply(method, std::tuple_cat(std::make_tuple(obj), tuple)); - std::ostringstream out; - RpcSerializer::write(out, result); + IpcMessageWriter out; + out.add(result); return out.str(); } template - static std::tuple readArgs(std::istringstream& in) { - return std::tuple{RpcSerializer::read(in)...}; + static std::tuple readArgs(IpcMessageReader& reader) { + return std::tuple{reader.template read()...}; } std::unordered_map -#include -#include - -#include -#include - -class RpcChannelFifoServer : public RpcChannel { -public: - RpcChannelFifoServer(const char* inPipe, const char* outPipe) { - fdIn = open(inPipe, O_RDONLY); - fdOut = open(outPipe, O_WRONLY); - } - - void send(const std::string& data) override { - ::write(fdOut, data.c_str(), data.size()); - ::write(fdOut, "\n", 1); - } - - std::string receive() override { - char buf[4096]; - int n = ::read(fdIn, buf, sizeof(buf) - 1); - if (n <= 0) { - return {}; - } - buf[n] = 0; - return std::string(buf); - } - -private: - int fdIn{}; - int fdOut{}; -}; int main() { + // Создание FIFO — часть пользовательского IPC‑кода. mkfifo("/tmp/rpc_in", 0666); mkfifo("/tmp/rpc_out", 0666); - RpcChannelFifoServer ch("/tmp/rpc_in", "/tmp/rpc_out"); + // IPC‑уровень: канал поверх pipe. + IpcPipeChannel ch("/tmp/rpc_in", "/tmp/rpc_out"); + // RPC‑уровень: скелет поверх того же канала. MyService realObj; MyServiceSkeleton skeleton(realObj);