first commit

This commit is contained in:
ghe0 2025-02-02 01:49:42 +02:00
commit 7057a0584d
Signed by: ghe0
GPG Key ID: 451028EE56A0FBB4
8 changed files with 1403 additions and 0 deletions

1
.gitignore vendored Normal file

@ -0,0 +1 @@
/target

1226
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

25
Cargo.toml Normal file

@ -0,0 +1,25 @@
[package]
name = "rust_test_grpc"
version = "0.1.0"
edition = "2021"
[[bin]]
name = "server"
path = "src/server.rs"
[[bin]]
name = "client"
path = "src/client.rs"
[dependencies]
futures = "0.3"
prost = "0.13"
prost-types = "0.13"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tokio = { version = "1.42", features = ["macros", "rt-multi-thread"] }
tokio-stream = "0.1"
tonic = "0.12"
[build-dependencies]
tonic-build = "0.12"

6
build.rs Normal file

@ -0,0 +1,6 @@
fn main() {
tonic_build::configure()
.build_server(true)
.compile_protos(&["dummy.proto"], &["proto"])
.unwrap_or_else(|e| panic!("Failed to compile protos {:?}", e));
}

27
dummy.proto Normal file

@ -0,0 +1,27 @@
syntax = "proto3";
package dummy;
message Empty {
}
message SomeRequest {
string what_client_sends = 1;
}
message SomeResponse {
string what_server_sends = 1;
}
message StreamRequest {
string what_client_sends = 1;
}
message StreamResponse {
string what_server_sends = 1;
}
service TestService {
rpc GetSomething (SomeRequest) returns (SomeResponse);
rpc ClientMessages (stream StreamRequest) returns (Empty);
rpc ServerMessages (Empty) returns (stream StreamResponse);
}

5
src/client.rs Normal file

@ -0,0 +1,5 @@
mod grpc;
fn main (){
println!("Hello! I am a client!");
}

3
src/grpc.rs Normal file

@ -0,0 +1,3 @@
pub mod dummy {
tonic::include_proto!("dummy");
}

110
src/server.rs Normal file

@ -0,0 +1,110 @@
use futures::Stream;
use std::pin::Pin;
use tokio_stream::{wrappers::ReceiverStream, StreamExt};
use tonic::{transport::Server, Request, Response, Status};
mod grpc;
// Import the generated server trait and messages.
use grpc::dummy::brain_daemon_server::{BrainDaemon, BrainDaemonServer};
use grpc::dummy::{Empty, SomeRequest, SomeResponse, StreamRequest, StreamResponse};
/// Our service implementation
#[derive(Debug, Default)]
pub struct MyBrainDaemon;
#[tonic::async_trait]
impl BrainDaemon for MyBrainDaemon {
/// Unary RPC: (SomeRequest) -> SomeResponse
async fn get_something(
&self,
request: Request<SomeRequest>,
) -> Result<Response<SomeResponse>, Status> {
// Extract the request message
let req = request.into_inner();
println!("Got a request: {:?}", req.what_client_sends);
// Build the response
let reply = SomeResponse {
what_server_sends: format!("Server says: Hello, {}!", req.what_client_sends),
};
Ok(Response::new(reply))
}
async fn client_messages(
&self,
request: Request<tonic::Streaming<StreamRequest>>,
) -> Result<Response<Empty>, Status> {
let mut stream = request.into_inner();
// Process the incoming stream
while let Some(item) = stream.next().await {
let message = item?;
println!("Received stream message: {}", message.what_client_sends);
// Do something with the message ...
}
// Return an Empty to the client
Ok(Response::new(Empty {}))
}
/// Server streaming RPC: (Empty) -> (stream StreamResponse)
type ServerMessagesStream =
Pin<Box<dyn Stream<Item = Result<StreamResponse, Status>> + Send + 'static>>;
async fn server_messages(
&self,
_request: Request<Empty>,
) -> Result<Response<Self::ServerMessagesStream>, Status> {
// Create a channel (or use any stream you like)
let (tx, rx) = tokio::sync::mpsc::channel(4);
// Spawn a task that sends data to the client
tokio::spawn(async move {
let messages = vec![
"Hello from the server!",
"Here's another message!",
"And one more message!",
];
for msg in messages {
// Send a single response
let response = StreamResponse {
what_server_sends: msg.to_string(),
};
if let Err(e) = tx.send(Ok(response)).await {
eprintln!("Failed to send response via stream: {e}");
return;
}
}
});
// Convert MPSC receiver into a Tonic-friendly stream
let output_stream = ReceiverStream::new(rx);
// Box it up and return
Ok(Response::new(
Box::pin(output_stream) as Self::ServerMessagesStream
))
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// The address on which your server will listen
let addr = "[::1]:50051".parse()?;
// Create an instance of your service
let daemon = MyBrainDaemon::default();
println!("BrainDaemon server listening on {}", addr);
// Run the server
Server::builder()
.add_service(BrainDaemonServer::new(daemon))
.serve(addr)
.await?;
Ok(())
}