{"id":23662756,"url":"https://github.com/kezhengjie/rpc","last_synced_at":"2025-09-19T06:59:41.043Z","repository":{"id":163339240,"uuid":"495680015","full_name":"kezhengjie/rpc","owner":"kezhengjie","description":"A header only and out of the box tcp rpc framework written in C++.","archived":false,"fork":false,"pushed_at":"2022-06-01T03:22:52.000Z","size":70,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-12-25T03:22:24.649Z","etag":null,"topics":["asio","compile-time-meta-programming","cpp","headeronly","rpc","rpc-framework"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kezhengjie.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-05-24T05:21:00.000Z","updated_at":"2022-08-16T16:32:06.000Z","dependencies_parsed_at":null,"dependency_job_id":"7228ede7-18f5-44c5-b69d-a2f4e6e0acf3","html_url":"https://github.com/kezhengjie/rpc","commit_stats":null,"previous_names":["kezhengjie/rpc"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kezhengjie%2Frpc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kezhengjie%2Frpc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kezhengjie%2Frpc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kezhengjie%2Frpc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kezhengjie","download_url":"https://codeload.github.com/kezhengjie/rpc/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239656203,"owners_count":19675564,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asio","compile-time-meta-programming","cpp","headeronly","rpc","rpc-framework"],"created_at":"2024-12-29T05:07:38.566Z","updated_at":"2025-09-19T06:59:35.979Z","avatar_url":"https://github.com/kezhengjie.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rpc\nA header only and out of the box tcp rpc framework written in C++.\n\n## Introduction\n\n### Protocol\nProtocol is a template specified on compile time.  \nServer,Client and Session are all based on it.  \n\n```c++\nusing SizeType = unsigned short;\nusing CmdType = unsigned short;\nusing Protocol = rpc::Protocol\u003cSizeType, CmdType\u003e;\n```\n\n**notice**: SizeType should be unsigned.If not,there will be a assert on debug mode and the program will be abort.  \n\n\n### Message\nAll message communicates on this framework should be wrapped by rpc::Protocol::MessageWrapper.  \nOtherwise the compile will be failed.  \n```c++\ntemplate \u003ctypename Protocol::Cmd cmd, typename MessageType,\n                  class MessageSizeGetter = DefaultMessageSizeGetter\u003cMessageType, typename Protocol::Size\u003e\u003e //optional\n```\n\n\n\n\nWrap your class with Cmd,Struct and SizeGetter(optional)  \n```c++\nstruct Foo1\n{\n    int i;\n    double d;\n};\n\n// Use sizeof() to calculate wrapped struct by default if you do not specify SizeGetter.\nusing MsgFoo1 = Protocol::MessageWrapper\u003c0x01, Foo1\u003e;\n\nstruct Foo2\n{\n    int i;\n    unsigned short textSize;\n    char text[120];\n\n    struct SizeGetter\n    {\n        unsigned short operator()(const Foo2 \u0026foo) const\n        {\n            return sizeof(foo.i) + sizeof(foo.textSize) + foo.textSize;\n        }\n    };\n};\n\n// If the size of wrapped struct is variable,you could specify a SizeGetter to calculate the message.\nusing MsgFoo2 = Protocol::MessageWrapper\u003c0x02, Foo2, Foo2::SizeGetter\u003e;\n```\n\n\n### Server\nBased on asio,```rpc::Server``` has a nice speed.  \n```c++\nconst char *const IP = \"127.0.0.1\";\nunsigned short port = 8890;\n\n// specify listen address.\nServer server(IP, port);\n\n// could only bind message callback by struct wrapped by rpc::Protocol::MessageWrapper,\n// that's why you need to specfify message cmd when using rpc::Protocol::MessageWrapper.\nserver.Bind\u003cMsgFoo1\u003e(\n    [](const MsgFoo1 \u0026req, Session \u0026session) -\u003e void\n    {\n        std::cout \u003c\u003c req-\u003ei \u003c\u003c std::endl;\n        std::cout \u003c\u003c req-\u003ed \u003c\u003c std::endl;\n\n        // every session have a buffer which is large to max protocol size.\n        // also it is concurrent safe.\n        MsgFoo2 \u0026ret2 = session.WriteBuffer();\n        ret2-\u003ei = 3;\n        static const char v[] = \"Hello\";\n        strcpy(ret2-\u003etext, v);\n        ret2-\u003etextSize = strlen(v);\n\n        // only class with Bytes() convert could be sent.\n        // all classes/struct wrapped by MessageWrapper has converter by default.\n        session.Write(ret2);\n    });\n    // this will block subsequent code.\n    server.Start();\n```\n\n\n### Client\n```c++\nconst char *const IP = \"127.0.0.1\";\nunsigned short port = 8890;\n\n// construct with server address.\nClient client(IP, port);\n\n// could only bind message callback by struct wrapped by rpc::Protocol::MessageWrapper,\n// that's why you need to specfify message cmd when using rpc::Protocol::MessageWrapper.\nclient.Bind\u003cMsgFoo2\u003e([](const MsgFoo2 \u0026req, Session \u0026session) -\u003e void \n{\n    std::string_view sv(req-\u003etext, req-\u003etextSize);\n    std::cout \u003c\u003c sv \u003c\u003c std::endl; \n});\n\n// this will also block.So we use thread here.\nstd::thread([\u0026]() -\u003e void{ client.Start(); }).detach();\n\n// WriteBuffer could be cast to any type wrapped by rpc::Protocol::MessageWrapper.\nMsgFoo1 \u0026msg = client.WriteBuffer();\nmsg-\u003ei = 1;\nmsg-\u003ed = 2;\n\n// only class with Bytes() convert could be sent.\n// all classes/struct wrapped by MessageWrapper has converter by default.\nclient.Send(msg);\n```\n\n\n\n\n## Full Usage\n```c++\n#include \"include/rpc/server.h\"\n#include \"include/rpc/session.h\"\n#include \"include/rpc/client.h\"\n#include \u003ciostream\u003e\n#include \u003cstring\u003e\n\n// All relevant classes is implemented with rpc::Protocol.\nusing Protocol = rpc::Protocol\u003cunsigned short, unsigned short\u003e;\nusing Server = rpc::Server\u003cProtocol\u003e;\nusing Client = rpc::Client\u003cProtocol\u003e;\nusing Session = rpc::Session\u003cProtocol\u003e;\n\nstruct Foo1\n{\n    int i;\n    double d;\n};\n\nstruct Foo2\n{\n    int i;\n    unsigned short textSize;\n    char text[120];\n\n    struct SizeGetter\n    {\n        unsigned short operator()(const Foo2 \u0026foo) const\n        {\n            return sizeof(foo.i) + sizeof(foo.textSize) + foo.textSize;\n        }\n    };\n};\n\n// wrap your own class with Protocol::MessageWrapper.\n\n// Use sizeof() to calculate wrapped struct by default.\nusing MsgFoo1 = Protocol::MessageWrapper\u003c0x01, Foo1\u003e;\n\n// If the size of wrapped struct is variable,you could specify a SizeGetter to calculate the message.\nusing MsgFoo2 = Protocol::MessageWrapper\u003c0x02, Foo2, Foo2::SizeGetter\u003e;\n\nint main(int argc, char **argv)\n{\n    const char *const IP = \"127.0.0.1\";\n    unsigned short port = 8890;\n\n    Server server(IP, port);\n    server.SetErrorHandler([](const asio::error_code \u0026ec) -\u003e void\n                           { std::cout \u003c\u003c ec \u003c\u003c \" \" \u003c\u003c ec.message() \u003c\u003c std::endl; });\n    server.Bind\u003cMsgFoo1\u003e(\n        [](const MsgFoo1 \u0026req, Session \u0026session) -\u003e void\n        {\n            std::cout \u003c\u003c req-\u003ei \u003c\u003c std::endl;\n            std::cout \u003c\u003c req-\u003ed \u003c\u003c std::endl;\n\n            // every session have a buffer which is large to max protocol size.\n            // also it is concurrent safe.\n            MsgFoo2 \u0026ret2 = session.WriteBuffer();\n            ret2-\u003ei = 3;\n            static const char v[] = \"Hello\";\n            strcpy(ret2-\u003etext, v);\n            ret2-\u003etextSize = strlen(v);\n\n            // only class with Bytes() convert could be sent.\n            // all classes/struct wrapped by MessageWrapper has converter by default.\n            session.Write(ret2);\n        });\n    std::thread([\u0026]() -\u003e void\n                { server.Start(); })\n        .detach();\n\n    std::this_thread::sleep_for(std::chrono::seconds(1));\n    Client client(IP, port);\n    client.SetErrorHandler([](const asio::error_code \u0026ec) -\u003e void\n                           { std::cout \u003c\u003c ec \u003c\u003c \" \" \u003c\u003c ec.message() \u003c\u003c std::endl; });\n    client.Bind\u003cMsgFoo2\u003e([](const MsgFoo2 \u0026req, Session \u0026session) -\u003e void\n    {\n            std::string_view sv(req-\u003etext, req-\u003etextSize);\n            std::cout \u003c\u003c sv \u003c\u003c std::endl; \n    });\n\n    std::thread([\u0026]() -\u003e void{ client.Start(); }).detach();\n    MsgFoo1 \u0026msg = client.WriteBuffer();\n    msg-\u003ei = 1;\n    msg-\u003ed = 2;\n    std::this_thread::sleep_for(std::chrono::seconds(1));\n    client.Send(msg);\n    std::this_thread::sleep_for(std::chrono::seconds(100));\n}\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkezhengjie%2Frpc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkezhengjie%2Frpc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkezhengjie%2Frpc/lists"}