Una biblioteca liviana que le permite enviar y recibir objetos a través de TCP o UDP. ObjectTranport pretende ser un marco de red lo más simple y liviano posible.
Hay múltiples opciones de serialización disponibles, como Protobuf. La serialización es inyectable y usted puede implementar la suya propia.
ObjectTransport se divide en paquetes separados según sus necesidades y están disponibles en nuget. Consulte las instrucciones de instalación para obtener más detalles: https://github.com/RhynoVDS/ObjectTransport/wiki/Installation
Puede iniciar un servidor TCP con el siguiente código:
var server = ObjectTransport . Factory . CreateTCPServer ( )
. UseJSONserialization ( ) ;
. Build ( ) ;
//Start the TCP server on port 123
server . Start ( "127.0.0.1" , 123 ) ;
o puedes iniciar un servidor UDP
var server = ObjectTransport . Factory . CreateUDPServer ( )
. UseJSONserialization ( ) ;
. Build ( ) ;
//Start the UDP server on port 123
server . Start ( "127.0.0.1" , 123 ) ;
En este ejemplo tenemos un escenario en el que queremos manejar un usuario que inicia sesión en el servidor. Supongamos que tenemos una clase simple llamada "LoginModel". Por ahora esta clase solo tiene el campo "Nombre de usuario"
public class LoginModel
{
public string Username { get ; set ; }
}
Queremos que el servidor reciba este objeto y lo maneje. Esto se puede hacer usando la función "Recibir":
server . Receive < LoginModel > ( lm =>
{
Console . WriteLine ( lm . Username ) ;
} )
. Execute ( ) ;
En el código anterior, especificamos que cuando el servidor reciba un objeto de tipo "LoginModel", ejecute la lambda proporcionada. Luego escribimos el Nombre de Usuario en la consola.
Es posible configurar múltiples funciones de recepción y manejar otros tipos:
server . Receive < LoginModel > ( lm => .. . ) . Execute ( ) ;
server . Receive < LogOutModel > ( lm => .. . ) . Execute ( ) ;
server . Receive < PlayerPosition > ( lm => .. . ) . Execute ( ) ;
.. .
Puede iniciar un cliente TCP con el siguiente 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 un objeto a través del canal, utilice la función "Enviar":
var loginRequest = new LoginModel ( )
loginRequest . Username = "TestUser" ;
client . Send ( loginRequest ) . Execute ( ) ;
En el siguiente ejemplo, mostraremos cómo un servidor/cliente puede responder a un objeto recibido.
En nuestro ejemplo anterior, actualmente estamos enviando un nombre de usuario al servidor pero no nuestra contraseña, lo cual no es muy seguro. En este ejemplo, actualizamos nuestro modelo para que tenga un campo "Contraseña":
public class LoginModel
{
public string Username { get ; set ; }
public string Password { get ; set ; }
}
Nuestro cliente necesita enviar una solicitud de inicio de sesión al servidor y ahora también deberá enviar su contraseña. Debido a esto, queremos manejar cualquier respuesta a nuestra solicitud, incluido si el inicio de sesión fue exitoso o no. Para manejar esto, creamos dos nuevas clases "LoginSuccess" y "LoginFailure".
public class LoginSuccess
{
public string Name { get ; set ; }
public string Password { get ; set ; }
}
public class LoginFailure
{
public string Message { get ; set ; }
}
En nuestro código de cliente, ahora usaremos la función "Respuesta" después de enviar el objeto de inicio de sesión. Cuando el servidor responde al objeto que fue enviado, el cliente manejará sus respuestas:
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 ( ) ;
En el ejemplo anterior, configuramos 2 identificadores de respuesta, uno para manejar "LoginSuccess" y otro para manejar "LoginFailure".
En el servidor, usaremos la función "Responder" después de recibir un modelo de inicio de sesión. Al usar esta función necesitamos usar una función/lambda que "devolverá" un objeto que será devuelto:
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 ( ) ;
Cuando hay varios clientes conectados, es posible especificar a qué cliente enviar un mensaje utilizando la función "Para". Puede especificar varios clientes en la función "Para".
server . Send ( anObjectToSend )
. To ( client1 , client2 , .. . ClientN )
. Execute ( ) ;
Puede enviar a todos los clientes utilizando lo siguiente.
//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
También puedes enviar a todos los clientes y especificar a quién excluir:
//Send to all clients except client 3
server . Send ( anObjectToSend )
. ToAllExcept ( client3 ) //Can exclude more eg: .ToAllExcept(client3,client2, ... clientN)
. Execute ( ) ;
Puedes especificar qué debe suceder cuando alguien se conecta o 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 ) ) ;
Al enviar objetos a través de UDP, el mensaje se envía sin confiabilidad. Puede activar UDP de manera confiable con lo siguiente:
client . SetReliable ( ) ;
Después de ejecutar la línea anterior, todos los objetos que se envíen se enviarán de manera confiable.
Otra opción es enviar sólo un mensaje específico de forma fiable. Lo siguiente demuestra esto:
client . Send ( anObjectToSend )
. Reliable ( ) ;
. Execute ( ) ;
Para desconectar uno o más clientes del servidor, puede utilizar la función DisconnectClient:
server . DisconnectClient ( client1 , client2 , .. . clientN ) ;