Thothrpc-это целостная, полностью совместимая с AOT, легкая, полная дуплексная и двунаправленная платформа RPC для .NET. Он мертв просто, но мощный. Это полностью агностик и модульная платформа, не делая предположений о том, какой проект вы создаете. Слои транспорта и сериализации объекта (для параметров и возврата методов), слои отделены от базовой библиотеки, а пользовательская реализация этих слоев легко предоставить вам свободу для легко создания системы RPC.
Конечно, было бы не просто, если бы эти слои не были включены для вас. Эта библиотека поставляется с надежным и упорядоченным транспортным уровнем UDP, построенным из Litenetlib, и слоя сериализации, созданного из Speepy Message Pack с безопасным транспортным решением HTTP/2 на дорожной карте.
Чтобы использовать следующий пример кода, вам нужны эти 3 пакета Nuget.
dotnet add package ThothRpc
dotnet add package ThothRpc.LiteNetLib
dotnet add package ThothRpc.MessagePack
--или--
Install-Package ThothRpc
Install-Package ThothRpc.LiteNetLib
Install-Package ThothRpc.MessagePack
public interface IClientService
{
[ ThothMethod ] // indicates that this method is callable from server
void PrintServerTime ( DateTime time ) ;
Task GetHelloWorld ( ) ;
}
public interface IServerService
{
[ ThothMethod ] // indicates that this method is callable from client
string GetHelloWorld ( ) ;
} // hubs are thread-safe and can be single instanced for your entire app,
// or you can have multiple instances - its up to you
var hub = ServerHubBuilder . BuildServer ( )
. UseTransport < LiteNetRpcServer > ( )
. UseMessagePack ( ) // any object that is serializable by MessagePack can be used in parameters or return values
. Build ( ) ;
var serverService = new ServerService ( hub ) ;
// register methods can be called multiple times to register multiple services to the same hub
hub . RegisterAs < IServerService > ( serverService ) ;
hub . Listen ( 9050 , "SomeConnectionKey" ) ;
// Thread.Sleep(60000);
// hub.Dispose(); // closes the connection
public class ServerService : IServerService
{
readonly ServerHub _hub ;
public ServerService ( ServerHub hub )
{
_hub = hub ;
Task . Run ( async ( ) =>
{
// print the current time to all clients every second
while ( true )
{
var now = DateTime . Now ;
// Fire and forget
_hub . InvokeForgetAllClients < IClientService > ( DeliveryMode . Sequenced ,
c => c . PrintServerTime ( now ) ) ;
await Task . Delay ( 1000 ) ;
}
} ) ;
}
public string GetHelloWorld ( ) // called from client
{
return "Hello World From Server!" ;
}
} var hub = ClientHubBuilder . BuildClient ( )
. UseTransport < LiteNetRpcClient > ( )
. UseMessagePack ( )
. Build ( ) ;
var clientService = new ClientService ( hub ) ;
hub . RegisterAs < IClientService > ( clientService ) ;
await hub . ConnectAsync ( "localhost" , 9050 , "SomeConnectionKey" ) ;
await clientService . GetHelloWorld ( ) ;
public class ClientService : IClientService
{
readonly ClientHub _hub ;
public ClientService ( ClientHub hub )
{
_hub = hub ;
}
public async Task GetHelloWorld ( )
{
// Method invocations not using fire-and-forget with a udp transport are always delivered reliable and ordered.
var helloWorld = await _hub . InvokeServerAsync < IServerService , string >
( s => s . GetHelloWorld ( ) ) ;
Console . WriteLine ( helloWorld ) ;
}
public void PrintServerTime ( DateTime time ) // called from server
{
Console . WriteLine ( $ "Server time: { time } " ) ;
}
}Код ниже такой же, как и выше, но на этот раз без каких -либо сильных наборов.
var hub = ServerHubBuilder . BuildServer ( )
. UseTransport < LiteNetRpcServer > ( )
. UseMessagePack ( )
. Build ( ) ;
var serverService = new ServerService ( hub ) ;
hub . Register ( serverService , "ServerService" ) ;
hub . Listen ( 9050 , "SomeConnectionKey" ) ;
public class ServerService
{
readonly ServerHub _hub ;
public ServerService ( ServerHub hub )
{
_hub = hub ;
Task . Run ( async ( ) =>
{
while ( true )
{
_hub . InvokeForgetAllClients ( DeliveryMode . Sequenced ,
"ClientService" , "PrintServerTime" , DateTime . Now ) ;
await Task . Delay ( 1000 ) ;
}
} ) ;
}
[ ThothMethod ]
public string GetHelloWorld ( )
{
return "Hello World From Server!" ;
}
} var hub = ClientHubBuilder . BuildClient ( )
. UseTransport < LiteNetRpcClient > ( )
. UseMessagePack ( )
. Build ( ) ;
var clientService = new ClientService ( hub ) ;
hub . Register ( clientService , "ClientService" ) ;
await hub . ConnectAsync ( "localhost" , 9050 , "SomeConnectionKey" ) ;
await clientService . GetHelloWorld ( ) ;
public class ClientService
{
readonly ClientHub _hub ;
public ClientService ( ClientHub hub )
{
_hub = hub ;
}
public async Task GetHelloWorld ( )
{
var helloWorld = await _hub . InvokeServerAsync < string >
( "ServerService" , "GetHelloWorld" ) ;
Console . WriteLine ( helloWorld ) ;
}
[ ThothMethod ]
public void PrintServerTime ( DateTime time )
{
Console . WriteLine ( $ "Server time: { time } " ) ;
}
} Тот (в его нынешнем состоянии) отлично подходит для…
Примечание. В настоящее время зашифрованный защищенный трафик еще не является функцией, но будет присутствовать в предстоящем транспорте HTTP/2. Тем не менее, реализация собственной системы шифрования легко с входными и выходными обратными вызовами.