The code below is based on example.proto.
A single-threaded gRPC server:
    example::v1::Example::AsyncService service;
    std::unique_ptr<grpc::Server> server;
    grpc::ServerBuilder builder;
    builder.AddListeningPort("0.0.0.0:50051", grpc::InsecureServerCredentials());
    builder.RegisterService(&service);
    server = builder.BuildAndStart();
    example::ServerShutdown shutdown{*server, grpc_context};
    register_handlers(grpc_context, service);
    grpc_context.run();
Unary rpc
                      example::v1::Example::AsyncService& service)
{
        grpc_context, service,
        [](RPC& rpc, RPC::Request& request) -> asio::awaitable<void>
        {
            RPC::Response response;
            response.set_integer(request.integer());
            co_await rpc.finish(response, grpc::Status::OK);
 
            
            co_await rpc.finish_with_error(grpc::Status::CANCELLED);
        },
        asio::detached);
}
 
Client-streaming rpc
                                 example::v1::Example::AsyncService& service)
{
    using RPC =
        grpc_context, service,
        [](RPC& rpc) -> asio::awaitable<void>
        {
            RPC::Request request;
            while (co_await rpc.read(request))
            {
                std::cout << "Request: " << request.integer() << std::endl;
            }
            RPC::Response response;
            response.set_integer(42);
            co_await rpc.finish(response, grpc::Status::OK);
 
            
            co_await rpc.finish_with_error(grpc::Status::CANCELLED);
        },
        asio::detached);
}
 
Server-streaming rpc
                                 example::v1::Example::AsyncService& service)
{
    using RPC =
        grpc_context, service,
        [](RPC& rpc, RPC::Request& request) -> asio::awaitable<void>
        {
            RPC::Response response;
            for (int i{}; i != request.integer(); ++i)
            {
                response.set_integer(i);
                if (!co_await rpc.write(response))
                {
                    co_return;
                }
            }
            co_await rpc.finish(grpc::Status::OK);
        },
        asio::detached);
}
 
Bidirectional-streaming rpc
                                        example::v1::Example::AsyncService& service)
{
        &example::v1::Example::AsyncService::RequestBidirectionalStreaming>;
        grpc_context, service,
        [](RPC& rpc) -> asio::awaitable<void>
        {
            RPC::Request request;
            RPC::Response response;
            while (co_await rpc.read(request))
            {
                response.set_integer(request.integer());
                if (!co_await rpc.write(response))
                {
                    co_return;
                }
            }
            response.set_integer(42);
            co_await rpc.write(response, grpc::WriteOptions{}.set_last_message());
            co_await rpc.finish(grpc::Status::OK);
        },
        asio::detached);
}