A lightweight library that allows you to send and receive objects over TCP or UDP. ObjectTranport aims to be a network framework that is as simple and lightweight as possible.
Multiple serialization options are available such as Protobuf. Serialization is injectable and you can implement your own.
ObjectTransport is split into seperate packages based off your needs and available on nuget. Plese see installation instructions for more details: https://github.com/RhynoVDS/ObjectTransport/wiki/Installation
You can start a TCP server with the following code
var server = ObjectTransport.Factory.CreateTCPServer("127.0.0.1",123)
.UseJSONserialization();
.Build();
or you can start a UDP server
var server = ObjectTransport.Factory.CreateUDPServer("127.0.0.1",123)
.UseJSONserialization();
.Build();
In this example we have a scenario where we want to handle a user logging into the server. Suppose we have a simple class called "LoginModel". For now this class only has the field "Username"
public class LoginModel
{
public string Username {get;set;}
}
We want the server to receive this object and handle it. This can be done using the "Receive" function:
server.Receive<LoginModel>(lm =>
{
Console.WriteLine(lm.Username);
})
.Execute();
In the above code, we specify that when the server Receives an object of type "LoginModel", execute the given lambda. We then write the Username to the console.
It is possible to set up multiple Receive functions and handle other types:
server.Receive<LoginModel>(lm => ... ).Execute();
server.Receive<LogOutModel>(lm => ... ).Execute();
server.Receive<PlayerPosition>(lm => ... ).Execute();
...
You can start a TCP client with the following code:
var client = ObjectTransport.Factory.CreateTCPClient("10.0.0.1",123);
To send an object over the channel, use the "Send" function:
var loginRequest = new LoginModel()
loginRequest.Username = "TestUser";
client.Send(loginRequest).Execute();
In the following example, we will show how a server/client can reply to a received object.
In our previous example, we are currently sending a Username to the server but not our password, which isn't very secure. In this example, we update our model to have a "Password" field:
public class LoginModel
{
public string Username {get;set;}
public string Password {get;set;}
}
Our client needs to send a login request to the server and will now need to send their password as well. Due to this, we want to handle any responses to our request including whether or not the login was successful. To handle this, we create two new classes "LoginSuccess" and "LoginFailure".
public class LoginSuccess
{
public string Name {get;set;}
public string Password {get;set;}
}
public class LoginFailure
{
public string Message {get;set;}
}
In our client code, we will now use the "Response" function after sending the login object. When the server replies to the object that was sent, the client will handle it's responses:
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();
In the above example, we setup 2 response handles, one to handle "LoginSuccess" and another to handle "LoginFailure".
On the server, we will use the "Reply" function after receiving a login model. When using this function we need use a function/lambda which will "return" an object that will be sent back:
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();
When multiple clients are connected, it is possible to specify which client to send a message to using the "To" function. You can specify multiple clients in the "To" function.
server.Send(anObjectToSend)
.To(client1,client2)
.Execute();
You can send to all clients using the following.
//Send to all clients except client 3
server.Send(anObjectToSend)
.ToAll()
.Execute();
You can also send to all clients and specify who to exclude:
//Send to all clients except client 3
server.Send(anObjectToSend)
.ToAllExcept(client3)
.Execute();
You can specify what should happen when someone connects or disconnects:
//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));
When sending objects over UDP, the message is sent without reliability. You can switch reliably on for UDP on with the following:
client.SetReliable();
After executing the above line, all objects that are sent will be sent reliably.
Another option is to send only a specific message reliably. The following demonstrates this:
client.Send(anObjectToSend)
.Reliable();
.Execute();