Coder Social home page Coder Social logo

sharprpc's Introduction

SharpRpc for C#

NuGet NuGet

Fast and efficient remote procedure call (RPC) framework for C#

Table of Contents

Features

  • High throughput capability (especialy while dealing with lot of small messages)
  • Low latency
  • Direct and backward calls (callbacks) in one contract
  • Optimization for message multicasting
  • Support of grpc-like streams (not implemented yet)
  • Configurable back-pressure (partially implemented)

Installation

This library is distributed via NuGet. We target .NET 4.71 and .NET 5.0. The library code is pure C#.

In order to get things working, you need you need to install the following NuGet packages.

Core library:

Install-Package SharpRpc.Core

Builder library with a code generator to generate messages and stubs for your RPC contract:

Install-Package SharpRpc.Builder

And a serializer library:

Install-Package MessagePack

Note: Only MessagePack is supported by now. More serializers will be added in near future...

Contract

To define a contract you need to create a public interface with RpcContract and RpcSerializer attributes.

[RpcContract]
[RpcSerializer(SerializerChoice.MessagePack)]
public interface MyContract
{
	[Rpc(RpcType.Call)]
	int MyRemoteCall(FooEntity entity, int p1);

	[Rpc(RpcType.Message)]
	void MyRemoteMessage(int p1, string p2);
}

Each remote call must be marked with Rpc attribute with one of four call types:

Rpc Type Call Initiator Description
Call Client Request from cleint to server.
Message Client One-way message from client to server.
Callback Server Request from server to client.
CallbackMessage Server One-way message from server to client.

Note: The contract interface is not for direct use and should not be implemented. Its only purpose is to supply metadata for code generation.

Data Contract

If you have objects as call parameters or results, they must be attributed according to specification of serializer you use. For example (MessagePack):

[MessagePackObject]
public class FooEntity
{
    [Key(0)]
    public string Name { get; set; }

    [Key(1)]
    public int Age { get; set; }

    [Key(2)]
    public double Height { get; set; }
}

Code generation

For each contract class the builder generates corresponding wrapper class which contains several subclasses to facilitate RPC communication. The builder composes this class name from contract name by adding '_Gen' suffix to it.

Class name Description
<contract_name>_Gen.Client Instantiate this class to call the service methods.
<contract_name>_Gen.ServiceBase Override this class to implements service methods.
<contract_name>_Gen.CallbackClient Instance of this class is avaialble as Client property on service side to allow server to callback the client.
<contract_name>_Gen.CallbackServiceBase Override this class to implement callback methods.

Note: CallbackClient and CallbackServiceBase classes are generated only if there is at least one callback or callback message in the contract.

Client setup

To setup communication from client side, create an endpoint first, than pass the endpoint instance to CreateClient method to create a client stub:

var endpoint = new TcpClientEndpoint("localhost", 812, TcpSecurity.None);
var client = MyContract_Gen.CreateClient(endpoint);

Endpoints carry all communication parameters and settings. Each communication transport has its own endpoint type. E.g. TCP transport uses TcpClientEndpoint and TcpServiceEdnpoint classes. Note: SharpRpc supports only TCP transport by now.

Connection may be initiated directly by calling TryConnectAsync method:

var connectResult = await client.Channel.TryConnectAsync();
// or
var connectResult = client.Channel.TryConnectAsync().Result;

Or inderectly by just calling any generated RPC method:

client.MyRemoteMessage(1, "23");

Server setup

First, implement service methods by overriding generated <contract_name>_Gen.ServiceBase class:

public class MyContractServiceImpl : MyContract_Gen.ServiceBase
{
    public override ValueTask<int> MyRemoteCall(FooEntity entity, int p1)
    {
        // ...
        return new ValueTask<int>();
    }

    public override ValueTask MyRemoteMessage(int p1, string p2)
    {
        // ...
        return new ValueTask();
    }
}

Second, create a RpcServer instance and supply it with a binding and an endpoint:

var endpoint = new TcpServerEndpoint(IPAddress.IPv6Any, 812, TcpServerSecurity.None);
var binding = MyContract_Gen.CreateBinding(() => new MyContractServiceImpl());
var server = new RpcServer(binding);
server.AddEndpoint(endpoint);

Note. You may attach multiple endpoint instances to a single server. E.g., you may have both insecure and secure(SSL) TCP endpoints for a single service.

Third, start the server:

server.Start();

You may stop server at any time by calling server.StopAsync();

Callbacks

Authentication

Currently, SharpRpc supports only basic login/password for authenticating clients and only certificates for authenticating servers. More authentication methods will be added in the future.

Basic authentication setup

On the client-side create BasicCredentials object and pass it to the endpoint:

var endpoint = new TcpClientEndpoint(address, port, security); endpoint.Credentials = new BasicCredentials("Admin", "zzzz");

Note: It's not advised to use basic authentication together with TcpSecuriot.None option. Login and password should not be send via unprocected transport.

On the server-side create a login/password validator class first:

internal class AuthValidator : PasswordValidator
{
    public ValueTask<string> Validate(string userName, string password)
    {
        if (userName == "Admin" && password == "zzzz")
            return ValueTask.FromResult<string>(null);

        return ValueTask.FromResult("Invalid credentials.");
    }
}

Than update Authenticator filed in the server endpoint:

var tcpEndpoint = new TcpServerEndpoint(IPAddress.IPv6Any, 812, security);
tcpEndpoint.Authenticator = new BasicAuthenticator(new AuthValidator());

If you have multiple endpoints authenticator should be configured separately for every one of them.

SSL Setup

Prebuilt messages

The prebuilt messages may be useful in cases when one message is multiple times, e.g. multicasting the same update for multiple clients. Prebuilding a message allows for significantly improved performance by excluding multiple serializations of the same message.

To use prebuild message sepcify EnablePrebuilder=true in the contract attribute:

[RpcServiceContract(EnablePrebuilder = true)]
public interface SomeRpcContract
{
}

This will signal the builder to generate a prebuilder class and overloads which accept prebuilt messages. Only operation contracts with RpcType.Message or RpcType.CallbackMessage allows prebuilding.

Then you may use the prebuilder to pre-serialize messages and send them to multiple clients:

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.