Uma biblioteca leve que permite enviar e receber objetos por TCP ou UDP. ObjectTranport pretende ser uma estrutura de rede tão simples e leve quanto possível.
Várias opções de serialização estão disponíveis, como Protobuf. A serialização é injetável e você pode implementar a sua própria.
ObjectTransport é dividido em pacotes separados com base em suas necessidades e disponíveis no nuget. Consulte as instruções de instalação para obter mais detalhes: https://github.com/RhynoVDS/ObjectTransport/wiki/Installation
Você pode iniciar um servidor TCP com o seguinte código:
var server = ObjectTransport . Factory . CreateTCPServer ( )
. UseJSONserialization ( ) ;
. Build ( ) ;
//Start the TCP server on port 123
server . Start ( "127.0.0.1" , 123 ) ;
ou você pode iniciar um servidor UDP
var server = ObjectTransport . Factory . CreateUDPServer ( )
. UseJSONserialization ( ) ;
. Build ( ) ;
//Start the UDP server on port 123
server . Start ( "127.0.0.1" , 123 ) ;
Neste exemplo, temos um cenário em que queremos lidar com o login de um usuário no servidor. Suponha que temos uma classe simples chamada “LoginModel”. Por enquanto esta classe possui apenas o campo "Nome de usuário"
public class LoginModel
{
public string Username { get ; set ; }
}
Queremos que o servidor receba este objeto e o trate. Isso pode ser feito usando a função "Receber":
server . Receive < LoginModel > ( lm =>
{
Console . WriteLine ( lm . Username ) ;
} )
. Execute ( ) ;
No código acima, especificamos que quando o servidor receber um objeto do tipo “LoginModel”, execute o lambda fornecido. Em seguida, escrevemos o nome de usuário no console.
É possível configurar múltiplas funções de Recebimento e lidar com outros tipos:
server . Receive < LoginModel > ( lm => .. . ) . Execute ( ) ;
server . Receive < LogOutModel > ( lm => .. . ) . Execute ( ) ;
server . Receive < PlayerPosition > ( lm => .. . ) . Execute ( ) ;
.. .
Você pode iniciar um cliente TCP com o seguinte código:
var client = ObjectTransport . Factory . CreateTCPClient ( )
. UseJSONserialization ( ) ;
. Build ( ) ;
//Start the client and connect to the target IP address and port
client . Start ( "10.0.0.1" , 123 ) ;
Para enviar um objeto pelo canal, utilize a função "Enviar":
var loginRequest = new LoginModel ( )
loginRequest . Username = "TestUser" ;
client . Send ( loginRequest ) . Execute ( ) ;
No exemplo a seguir, mostraremos como um servidor/cliente pode responder a um objeto recebido.
No nosso exemplo anterior, estamos enviando um nome de usuário para o servidor, mas não nossa senha, o que não é muito seguro. Neste exemplo, atualizamos nosso modelo para ter um campo “Senha”:
public class LoginModel
{
public string Username { get ; set ; }
public string Password { get ; set ; }
}
Nosso cliente precisa enviar uma solicitação de login ao servidor e agora também precisará enviar sua senha. Devido a isso, queremos lidar com quaisquer respostas à nossa solicitação, incluindo se o login foi bem-sucedido ou não. Para lidar com isso, criamos duas novas classes “LoginSuccess” e “LoginFailure”.
public class LoginSuccess
{
public string Name { get ; set ; }
public string Password { get ; set ; }
}
public class LoginFailure
{
public string Message { get ; set ; }
}
Em nosso código cliente, utilizaremos agora a função “Resposta” após enviar o objeto login. Quando o servidor responder ao objeto que foi enviado, o cliente tratará suas respostas:
var transport = ObjectTransport . Factory . CreateTCPClient ( "10.0.0.1" , 123 ) ;
var loginRequest = new LoginModel ( ) ;
loginRequest . Username = "TestUser" ;
loginRequest . Password = "A password" ;
transport . Send ( loginRequest )
. Response < LoginSuccess > ( ls => {
Console . WriteLine ( "Welcome Back {0}" , ls . Name ) ;
} )
. Response < LoginFailure > ( lr => {
Console . WriteLine ( lr . Message )
} )
. Execute ( ) ;
No exemplo acima, configuramos 2 identificadores de resposta, um para tratar "LoginSuccess" e outro para tratar "LoginFailure".
No servidor, utilizaremos a função “Responder” após receber um modelo de login. Ao usar esta função precisamos usar uma função/lambda que irá "retornar" um objeto que será enviado de volta:
server . Receive < LoginModel > ( )
. Reply ( lr => {
string user = string . empty ;
//Check if login is valid
if ( utilities . Login ( lr , out user ) )
{
//Return an object back to the client
var response = new LoginSuccess ( ) ;
response . Message = "Login Successful" ;
response . Name = user ;
return response ;
}
else
{
//Return an object back to the client
var response = new LoginFailure ( ) ;
response . Message = "Login Failed" ;
return response ;
}
} )
. Execute ( ) ;
Quando vários clientes estão conectados, é possível especificar para qual cliente enviar uma mensagem usando a função "Para". Você pode especificar vários clientes na função "Para".
server . Send ( anObjectToSend )
. To ( client1 , client2 , .. . ClientN )
. Execute ( ) ;
Você pode enviar para todos os clientes usando o seguinte.
//Send to all clients
server . Send ( anObjectToSend )
. ToAll ( )
. Execute ( ) ;
//Note that you don't actually need to specify ToAll anymore. By default the API will send to all
Você também pode enviar para todos os clientes e especificar quem excluir:
//Send to all clients except client 3
server . Send ( anObjectToSend )
. ToAllExcept ( client3 ) //Can exclude more eg: .ToAllExcept(client3,client2, ... clientN)
. Execute ( ) ;
Você pode especificar o que deve acontecer quando alguém se conecta ou desconecta:
//Setup onconnect handler
transport . OnClientConnect ( c => Console . WriteLine ( "A client has connected with ip {0}" , c . IPAddress ) ) ;
//Setup onDisconnect handler
transport . OnClientDisconnect ( c => Console . WriteLine ( "A client has disconnected with ip {0}" , c . IPAddress ) ) ;
Ao enviar objetos por UDP, a mensagem é enviada sem confiabilidade. Você pode ativar o UDP de maneira confiável com o seguinte:
client . SetReliable ( ) ;
Após executar a linha acima, todos os objetos enviados serão enviados de forma confiável.
Outra opção é enviar de forma confiável apenas uma mensagem específica. O seguinte demonstra isso:
client . Send ( anObjectToSend )
. Reliable ( ) ;
. Execute ( ) ;
Para desconectar um ou mais clientes do servidor, você pode usar a função DisconnectClient:
server . DisconnectClient ( client1 , client2 , .. . clientN ) ;