hmm
This commit is contained in:
+6
-33
@@ -1,48 +1,21 @@
|
|||||||
#include "MyService.proxy.h"
|
#include "MyService.proxy.h"
|
||||||
#include "rpc/RpcChannel.h"
|
#include "rpc/IpcPipeChannel.h"
|
||||||
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
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() {
|
int main() {
|
||||||
|
// Создание FIFO — часть пользовательского IPC‑кода.
|
||||||
mkfifo("/tmp/rpc_in", 0666);
|
mkfifo("/tmp/rpc_in", 0666);
|
||||||
mkfifo("/tmp/rpc_out", 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);
|
MyServiceProxy proxy(ch);
|
||||||
|
|
||||||
int r = proxy.add(7, 8);
|
int r = proxy.add(7, 8);
|
||||||
std::cout << "RESULT: " << r << std::endl;
|
std::cout << "RESULT: " << r << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// Примитивный IPC‑формат сообщений:
|
||||||
|
// комбинация std::ostringstream / std::istringstream с удобным API add<T>/read<T>.
|
||||||
|
|
||||||
|
class IpcMessageWriter {
|
||||||
|
public:
|
||||||
|
template<typename T>
|
||||||
|
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<typename T>
|
||||||
|
T read() {
|
||||||
|
T v{};
|
||||||
|
in_ >> v;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::istringstream in_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "RpcChannel.h"
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// 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};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
+7
-8
@@ -1,9 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "RpcChannel.h"
|
#include "RpcChannel.h"
|
||||||
#include "RpcSerializer.h"
|
#include "IpcMessage.h"
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class RpcClient {
|
class RpcClient {
|
||||||
@@ -12,22 +11,22 @@ public:
|
|||||||
|
|
||||||
template<typename Ret, typename... Args>
|
template<typename Ret, typename... Args>
|
||||||
Ret call(const std::string& method, const Args&... args) {
|
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::string resp = channel.receive();
|
||||||
std::istringstream in(resp);
|
IpcMessageReader reader(resp);
|
||||||
|
|
||||||
return RpcSerializer::read<Ret>(in);
|
return reader.template read<Ret>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
+12
-15
@@ -1,9 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "RpcSerializer.h"
|
#include "IpcMessage.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@@ -16,21 +15,19 @@ public:
|
|||||||
Ret (Obj::*method)(Args...)) {
|
Ret (Obj::*method)(Args...)) {
|
||||||
handlers[name] =
|
handlers[name] =
|
||||||
[instance, method](const std::string& req) -> std::string {
|
[instance, method](const std::string& req) -> std::string {
|
||||||
std::istringstream in(req);
|
IpcMessageReader reader(req);
|
||||||
|
|
||||||
// пропустить имя метода
|
// пропустить имя метода
|
||||||
std::string skip;
|
(void)reader.template read<std::string>();
|
||||||
in >> skip;
|
|
||||||
|
|
||||||
// читать аргументы и вызвать метод
|
// читать аргументы и вызвать метод
|
||||||
return callMethod<Ret, Obj, Args...>(instance, method, in);
|
return callMethod<Ret, Obj, Args...>(instance, method, reader);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string dispatch(const std::string& request) {
|
std::string dispatch(const std::string& request) {
|
||||||
std::istringstream in(request);
|
IpcMessageReader reader(request);
|
||||||
std::string method;
|
const std::string method = reader.read<std::string>();
|
||||||
in >> method;
|
|
||||||
|
|
||||||
auto it = handlers.find(method);
|
auto it = handlers.find(method);
|
||||||
if (it == handlers.end()) {
|
if (it == handlers.end()) {
|
||||||
@@ -44,19 +41,19 @@ private:
|
|||||||
template<typename Ret, typename Obj, typename... Args>
|
template<typename Ret, typename Obj, typename... Args>
|
||||||
static std::string callMethod(Obj* obj,
|
static std::string callMethod(Obj* obj,
|
||||||
Ret (Obj::*method)(Args...),
|
Ret (Obj::*method)(Args...),
|
||||||
std::istringstream& in) {
|
IpcMessageReader& reader) {
|
||||||
auto tuple = readArgs<Args...>(in);
|
auto tuple = readArgs<Args...>(reader);
|
||||||
Ret result =
|
Ret result =
|
||||||
std::apply(method, std::tuple_cat(std::make_tuple(obj), tuple));
|
std::apply(method, std::tuple_cat(std::make_tuple(obj), tuple));
|
||||||
|
|
||||||
std::ostringstream out;
|
IpcMessageWriter out;
|
||||||
RpcSerializer::write(out, result);
|
out.add(result);
|
||||||
return out.str();
|
return out.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
static std::tuple<Args...> readArgs(std::istringstream& in) {
|
static std::tuple<Args...> readArgs(IpcMessageReader& reader) {
|
||||||
return std::tuple<Args...>{RpcSerializer::read<Args>(in)...};
|
return std::tuple<Args...>{reader.template read<Args>()...};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<std::string,
|
std::unordered_map<std::string,
|
||||||
|
|||||||
+5
-34
@@ -1,48 +1,19 @@
|
|||||||
#include "MyService.h"
|
#include "MyService.h"
|
||||||
#include "MyService.skeleton.h"
|
#include "MyService.skeleton.h"
|
||||||
|
|
||||||
#include "rpc/RpcChannel.h"
|
#include "rpc/IpcPipeChannel.h"
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
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() {
|
int main() {
|
||||||
|
// Создание FIFO — часть пользовательского IPC‑кода.
|
||||||
mkfifo("/tmp/rpc_in", 0666);
|
mkfifo("/tmp/rpc_in", 0666);
|
||||||
mkfifo("/tmp/rpc_out", 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;
|
MyService realObj;
|
||||||
MyServiceSkeleton skeleton(realObj);
|
MyServiceSkeleton skeleton(realObj);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user