{"id":17344142,"url":"https://github.com/typhoonzero/grpc_zerocopy_async_example","last_synced_at":"2026-05-03T19:33:06.196Z","repository":{"id":99429202,"uuid":"123888234","full_name":"typhoonzero/grpc_zerocopy_async_example","owner":"typhoonzero","description":"Example project of using grpc to do zerocopy large buffer communication.","archived":false,"fork":false,"pushed_at":"2018-03-14T10:03:32.000Z","size":53,"stargazers_count":0,"open_issues_count":1,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-03-27T09:49:21.627Z","etag":null,"topics":["grpc","zero-copy"],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/typhoonzero.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2018-03-05T08:26:08.000Z","updated_at":"2020-11-18T07:50:03.000Z","dependencies_parsed_at":null,"dependency_job_id":"360f004d-b6f7-456c-a83c-985f870a1012","html_url":"https://github.com/typhoonzero/grpc_zerocopy_async_example","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/typhoonzero/grpc_zerocopy_async_example","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typhoonzero%2Fgrpc_zerocopy_async_example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typhoonzero%2Fgrpc_zerocopy_async_example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typhoonzero%2Fgrpc_zerocopy_async_example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typhoonzero%2Fgrpc_zerocopy_async_example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/typhoonzero","download_url":"https://codeload.github.com/typhoonzero/grpc_zerocopy_async_example/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typhoonzero%2Fgrpc_zerocopy_async_example/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32582694,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T06:36:36.687Z","status":"ssl_error","status_checked_at":"2026-05-03T06:36:09.306Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["grpc","zero-copy"],"created_at":"2024-10-15T16:24:12.579Z","updated_at":"2026-05-03T19:33:06.163Z","avatar_url":"https://github.com/typhoonzero.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"NOTE: this is copied from https://github.com/grpc/grpc/examples/cpp to show how to use zerocopy transfer.\n\n# gRPC C++ Hello World Tutorial\n\n### Install gRPC\nMake sure you have installed gRPC on your system. Follow the instructions here:\n[https://github.com/grpc/grpc/blob/master/INSTALL](../../../INSTALL.md).\n\n### Get the tutorial source code\n\nThe example code for this and our other examples lives in the `examples`\ndirectory. Clone this repository to your local machine by running the\nfollowing command:\n\n\n```sh\n$ git clone -b $(curl -L https://grpc.io/release) https://github.com/grpc/grpc\n```\n\nChange your current directory to examples/cpp/helloworld\n\n```sh\n$ cd examples/cpp/helloworld/\n```\n\n### Defining a service\n\nThe first step in creating our example is to define a *service*: an RPC\nservice specifies the methods that can be called remotely with their parameters\nand return types. As you saw in the\n[overview](#protocolbuffers) above, gRPC does this using [protocol\nbuffers](https://developers.google.com/protocol-buffers/docs/overview). We\nuse the protocol buffers interface definition language (IDL) to define our\nservice methods, and define the parameters and return\ntypes as protocol buffer message types. Both the client and the\nserver use interface code generated from the service definition.\n\nHere's our example service definition, defined using protocol buffers IDL in\n[helloworld.proto](../../protos/helloworld.proto). The `Greeting`\nservice has one method, `hello`, that lets the server receive a single\n`HelloRequest`\nmessage from the remote client containing the user's name, then send back\na greeting in a single `HelloReply`. This is the simplest type of RPC you\ncan specify in gRPC - we'll look at some other types later in this document.\n\n```protobuf\nsyntax = \"proto3\";\n\noption java_package = \"ex.grpc\";\n\npackage helloworld;\n\n// The greeting service definition.\nservice Greeter {\n  // Sends a greeting\n  rpc SayHello (HelloRequest) returns (HelloReply) {}\n}\n\n// The request message containing the user's name.\nmessage HelloRequest {\n  string name = 1;\n}\n\n// The response message containing the greetings\nmessage HelloReply {\n  string message = 1;\n}\n\n```\n\n\u003ca name=\"generating\"\u003e\u003c/a\u003e\n### Generating gRPC code\n\nOnce we've defined our service, we use the protocol buffer compiler\n`protoc` to generate the special client and server code we need to create\nour application. The generated code contains both stub code for clients to\nuse and an abstract interface for servers to implement, both with the method\ndefined in our `Greeting` service.\n\nTo generate the client and server side interfaces:\n\n```sh\n$ make helloworld.grpc.pb.cc helloworld.pb.cc\n```\nWhich internally invokes the proto-compiler as:\n\n```sh\n$ protoc -I ../../protos/ --grpc_out=. --plugin=protoc-gen-grpc=grpc_cpp_plugin ../../protos/helloworld.proto\n$ protoc -I ../../protos/ --cpp_out=. ../../protos/helloworld.proto\n```\n\n### Writing a client\n\n- Create a channel. A channel is a logical connection to an endpoint. A gRPC\n  channel can be created with the target address, credentials to use and\n  arguments as follows\n\n    ```cpp\n    auto channel = CreateChannel(\"localhost:50051\", InsecureChannelCredentials());\n    ```\n\n- Create a stub. A stub implements the rpc methods of a service and in the\n  generated code, a method is provided to created a stub with a channel:\n\n    ```cpp\n    auto stub = helloworld::Greeter::NewStub(channel);\n    ```\n\n- Make a unary rpc, with `ClientContext` and request/response proto messages.\n\n    ```cpp\n    ClientContext context;\n    HelloRequest request;\n    request.set_name(\"hello\");\n    HelloReply reply;\n    Status status = stub-\u003eSayHello(\u0026context, request, \u0026reply);\n    ```\n\n- Check returned status and response.\n\n    ```cpp\n    if (status.ok()) {\n      // check reply.message()\n    } else {\n      // rpc failed.\n    }\n    ```\n\nFor a working example, refer to [greeter_client.cc](greeter_client.cc).\n\n### Writing a server\n\n- Implement the service interface\n\n    ```cpp\n    class GreeterServiceImpl final : public Greeter::Service {\n      Status SayHello(ServerContext* context, const HelloRequest* request,\n          HelloReply* reply) override {\n        std::string prefix(\"Hello \");\n        reply-\u003eset_message(prefix + request-\u003ename());\n        return Status::OK;\n      }\n    };\n\n    ```\n\n- Build a server exporting the service\n\n    ```cpp\n    GreeterServiceImpl service;\n    ServerBuilder builder;\n    builder.AddListeningPort(\"0.0.0.0:50051\", grpc::InsecureServerCredentials());\n    builder.RegisterService(\u0026service);\n    std::unique_ptr\u003cServer\u003e server(builder.BuildAndStart());\n    ```\n\nFor a working example, refer to [greeter_server.cc](greeter_server.cc).\n\n### Writing asynchronous client and server\n\ngRPC uses `CompletionQueue` API for asynchronous operations. The basic work flow\nis\n- bind a `CompletionQueue` to a rpc call\n- do something like a read or write, present with a unique `void*` tag\n- call `CompletionQueue::Next` to wait for operations to complete. If a tag\n  appears, it indicates that the corresponding operation is complete.\n\n#### Async client\n\nThe channel and stub creation code is the same as the sync client.\n\n- Initiate the rpc and create a handle for the rpc. Bind the rpc to a\n  `CompletionQueue`.\n\n    ```cpp\n    CompletionQueue cq;\n    auto rpc = stub-\u003eAsyncSayHello(\u0026context, request, \u0026cq);\n    ```\n\n- Ask for reply and final status, with a unique tag\n\n    ```cpp\n    Status status;\n    rpc-\u003eFinish(\u0026reply, \u0026status, (void*)1);\n    ```\n\n- Wait for the completion queue to return the next tag. The reply and status are\n  ready once the tag passed into the corresponding `Finish()` call is returned.\n\n    ```cpp\n    void* got_tag;\n    bool ok = false;\n    cq.Next(\u0026got_tag, \u0026ok);\n    if (ok \u0026\u0026 got_tag == (void*)1) {\n      // check reply and status\n    }\n    ```\n\nFor a working example, refer to [greeter_async_client.cc](greeter_async_client.cc).\n\n#### Async server\n\nThe server implementation requests a rpc call with a tag and then wait for the\ncompletion queue to return the tag. The basic flow is\n\n- Build a server exporting the async service\n\n    ```cpp\n    helloworld::Greeter::AsyncService service;\n    ServerBuilder builder;\n    builder.AddListeningPort(\"0.0.0.0:50051\", InsecureServerCredentials());\n    builder.RegisterService(\u0026service);\n    auto cq = builder.AddCompletionQueue();\n    auto server = builder.BuildAndStart();\n    ```\n\n- Request one rpc\n\n    ```cpp\n    ServerContext context;\n    HelloRequest request;\n    ServerAsyncResponseWriter\u003cHelloReply\u003e responder;\n    service.RequestSayHello(\u0026context, \u0026request, \u0026responder, \u0026cq, \u0026cq, (void*)1);\n    ```\n\n- Wait for the completion queue to return the tag. The context, request and\n  responder are ready once the tag is retrieved.\n\n    ```cpp\n    HelloReply reply;\n    Status status;\n    void* got_tag;\n    bool ok = false;\n    cq.Next(\u0026got_tag, \u0026ok);\n    if (ok \u0026\u0026 got_tag == (void*)1) {\n      // set reply and status\n      responder.Finish(reply, status, (void*)2);\n    }\n    ```\n\n- Wait for the completion queue to return the tag. The rpc is finished when the\n  tag is back.\n\n    ```cpp\n    void* got_tag;\n    bool ok = false;\n    cq.Next(\u0026got_tag, \u0026ok);\n    if (ok \u0026\u0026 got_tag == (void*)2) {\n      // clean up\n    }\n    ```\n\nTo handle multiple rpcs, the async server creates an object `CallData` to\nmaintain the state of each rpc and use the address of it as the unique tag. For\nsimplicity the server only uses one completion queue for all events, and runs a\nmain loop in `HandleRpcs` to query the queue.\n\nFor a working example, refer to [greeter_async_server.cc](greeter_async_server.cc).\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftyphoonzero%2Fgrpc_zerocopy_async_example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftyphoonzero%2Fgrpc_zerocopy_async_example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftyphoonzero%2Fgrpc_zerocopy_async_example/lists"}