Last active
January 19, 2021 02:21
-
-
Save laysakura/8baf784923181042aa54dce179d76aa4 to your computer and use it in GitHub Desktop.
tarpc !Sync server
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // [dependencies] | |
| // futures = "0.3" | |
| // tarpc = {version = "0.24", features = ["full"]} | |
| // tokio = {version = "1.0", features = ["macros"]} | |
| use futures::{ | |
| future::{self}, | |
| prelude::*, | |
| }; | |
| use std::{ | |
| net::{IpAddr, SocketAddr}, | |
| pin::Pin, | |
| }; | |
| use tarpc::server::Channel; | |
| use tarpc::{ | |
| context, | |
| server::{self, Handler}, | |
| tokio_serde::formats::Json, | |
| }; | |
| use tokio::task; | |
| // This is the service definition. It looks a lot like a trait definition. | |
| // It defines one RPC, hello, which takes one arg, name, and returns a String. | |
| #[tarpc::service] | |
| pub trait World { | |
| /// Returns a greeting for name. | |
| async fn hello(name: String) -> String; | |
| } | |
| type BoxFut<O> = Pin<Box<dyn Future<Output = O>>>; | |
| // This is the type that implements the generated World trait. It is the business logic | |
| // and is used to start the server. | |
| #[derive(Clone)] | |
| pub struct HelloServer(SocketAddr); | |
| impl World for HelloServer { | |
| type HelloFut = BoxFut<String>; | |
| fn hello(self, _: context::Context, name: String) -> Self::HelloFut { | |
| async move { format!("Hello, {}!", name) }.boxed_local() | |
| } | |
| } | |
| #[tokio::main] | |
| async fn main() -> std::io::Result<()> { | |
| let local = task::LocalSet::new(); | |
| local | |
| .run_until(async move { | |
| let port = "8888" | |
| .parse() | |
| .unwrap_or_else(|e| panic!(r#"--port value "{}" invalid: {}"#, "8888", e)); | |
| let server_addr = (IpAddr::from([0, 0, 0, 0]), port); | |
| let listener = tarpc::serde_transport::tcp::listen(&server_addr, Json::default) | |
| .await | |
| .unwrap(); | |
| listener | |
| // Ignore accept errors. | |
| .filter_map(|r| future::ready(r.ok())) | |
| .map(server::BaseChannel::with_defaults) | |
| // Limit channels to 1 per IP. | |
| .max_channels_per_key(1, |t| t.as_ref().peer_addr().unwrap().ip()) | |
| // serve is generated by the service attribute. It takes as input any type implementing | |
| // the generated World trait. | |
| .map(|channel| { | |
| let server = HelloServer(channel.as_ref().as_ref().peer_addr().unwrap()); | |
| channel.respond_with(server.serve()).try_for_each( | |
| |request_handler| async move { | |
| request_handler.await; | |
| Ok(()) | |
| }, | |
| ) | |
| }) | |
| // Max 10 channels. | |
| .buffer_unordered(10) | |
| .for_each(|_| async {}) | |
| .await; | |
| }) | |
| .await; | |
| Ok(()) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment