Adicionalmente al API de Alto Nivel de networking que proporcionamos - lo cual proporciona sistemas fácil de utilizar para manejar jugadores, GameObjects en red, y otros requerimientos comunes - nosotros también damos acceso a un API de más bajo nivel llamado “Transport Layer”. Esto le proporciona a usted la habilidad de bajo nivel, la cual puede ser útil si usted tiene requerimientos más específicos o avanzados para el networking de su juego.
El Transport Layer está dentro de una capa delgada que funciona encima del networking (red) del sistema operativo basado en sockets. Es capaz de enviar y recibir mensajes representados como arreglos de bytes, y ofrece una cantidad de diferentes opciones “quality of service” (calidad de servicio) para diferentes escenarios. Se enfoca en flexibilidad y rendimiento, y expone un API dentro de la clase UnityEngine.Networking.NetworkTransport.
La Transport Layer soporte servicios bases para la comunicación en red. Estos servicios base incluye:
El Transport Layer puede utilizar dos protocolos: UDP para comunicaciones genéricas, y WebSockets para WebGL. Para utilizar el Transport Layer directamente, el flujo de trabajo típico sería como el que sigue:
Cuando inicialice el Network Transport Layer, usted puede escoger entre la inicialización predeterminado, sin argumentos, o usted puede proporcionar parámetros que controlan el comportamiento general de la capa en red, tal como el maximum packet size (tamaño máximo del paquete) y thread timeout limit (tiempo limite del thread).
// Initializing the Transport Layer with no arguments (default settings)
NetworkTransport.Init();
// An example of initializing the Transport Layer with custom settings
GlobalConfig gConfig = new GlobalConfig();
gConfig.MaxPacketSize = 500;
NetworkTransport.Init(gConfig);
En el segundo ejemplo arriba, el Transport Layer está inicializado con un valor personalizado “MaxPacketSize” especificado a 500. Los valores personalizados Init deberían solamente ser utilizados si usted tiene un ambiente inusual de networking y son familiares con los ajustes específicos que usted necesita. Como regla, si usted está desarrollando un juego multi-jugador típico diseñado a ser jugado a través del internet, los ajustes Init() predeterminados sin argumentos deberían ser apropiados.
El siguiente paso es configurar una conexión entre los compañeros. Usted podría definir varios canales de comunicación, cada uno con un nivel de quality of service diferente especificado para que encaje con los típicos específicos de mensajes que usted quiere enviar, y su importancia relativa dentro de su juego.
ConnectionConfig config = new ConnectionConfig();
int myReiliableChannelId = config.AddChannel(QosType.Reliable);
int myUnreliableChannelId = config.AddChannel(QosType.Unreliable);
En el ejemplo de arriba, nosotros definimos dos canales de comunicación con diferentes valores de quality of service. “QosType.Reliable” enviará un mensaje y se asegurará que el mensaje es enviado, mientras que “QosType.Unreliable” enviará un mensaje sin asegurarse, pero lo hará más rápido.
También es posible especificar unos ajustes de configuración específicamente para cada conexión, al ajustes propiedades en el objeto ConnectionConfig. Sin embargo, cuando haga una conexión de un cliente a otro, los ajustes deberían ser los mismo para ambos compañeros conectados o la conexión fallará con un error CRCMismatch
.
El paso final de la configuración en red es la definición de topología. La topología en red define qué tantas conexiones son permitidas y qué configuración en red será utilizada.
HostTopology topology = new HostTopology(config, 10);
Here we created a topology that allows up to 10 connections, each of them are configured by the parameters defined in previous step.
As all preliminary steps are done, we can create the host (open socket):
int hostId = NetworkTransport.AddHost(topology, 8888);
Here we add a new host on port 8888 and any ip addresses. This host will support up to 10 connections, and each connection will have parameters as we defined in config
object.
When the host is created, we can start our communication. To do this we send different commands to the host and check its status. There are 3 main commands that we can send:
connectionId = NetworkTransport.Connect(hostId, "192.16.7.21", 8888, 0, out error);
NetworkTransport.Disconnect(hostId, connectionId, out error);
NetworkTransport.Send(hostId, connectionId, myReiliableChannelId, buffer, bufferLength, out error);
connectionId
, using the reliable channel with the id that equals myReiliableChannelId
. The message should be stored in buffer[]
and the length of the message should be defined by bufferLength
.For checking the host status you can use two functions:
NetworkTransport.Receive(out recHostId, out connectionId, out channelId, recBuffer, bufferSize, out dataSize, out error);
NetworkTransport.ReceiveFromHost(recHostId, out connectionId, out channelId, recBuffer, bufferSize, out dataSize, out error);
Both of them returns an event. The first function returns events from any host (and return host id via recHostId
). The second form checks the host with id recHostId
. You can use any of these functions inside the Update()
method:
void Update()
{
int recHostId;
int connectionId;
int channelId;
byte[] recBuffer = new byte[1024];
int bufferSize = 1024;
int dataSize;
byte error;
NetworkEventType recData = NetworkTransport.Receive(out recHostId, out connectionId, out channelId, recBuffer, bufferSize, out dataSize, out error);
switch (recData)
{
case NetworkEventType.Nothing: //1
break;
case NetworkEventType.ConnectEvent: //2
break;
case NetworkEventType.DataEvent: //3
break;
case NetworkEventType.DisconnectEvent: //4
break;
}
}
myConnectionId = NetworkTransport.Connect(hostId, "192.16.7.21", 8888, 0, out error);
NetworkEventType recData = NetworkTransport.Receive(out recHostId, out connectionId, out channelId, recBuffer, bufferSize, out dataSize, out error);
switch (recData)
{
case NetworkEventType.ConnectEvent:
if(myConnectionId == connectionId)
//my active connect request approved
else
//somebody else connect to me
break;
//...
}
recHostId
will define a host, connectionId will define a connection, channelId
will define a channel, and dataSize
will define the size of the received data. If recBuffer
is big enough to contain data, data will be copied in the buffer. If not, error
will contain MessageToLong
error and you will need to reallocate the buffer and call this function again.myConnectionId = NetworkTransport.Connect(hostId, "192.16.7.21", 8888, 0, out error);
NetworkEventType recData = NetworkTransport.Receive(out recHostId, out connectionId, out channelId, recBuffer, bufferSize, out dataSize, out error);
switch (recData)
{
case NetworkEventType. DisconnectEvent:
if(myConnectionId == connectionId)
//cannot connect by some reason see error
else
//one of the established connection has been disconnected
break;
\\...
}
WebSocket on client is supported. For the client side, all the steps described above (including topology and configuration) should be the same. Web clients can connect to the server only, where the server is a standalone player (Win, Mac or Linux only). On the server you should call
NetworkTransport.AddWebsocketHost(topology, port, ip);
Dónde la dirección ip
es la dirección que escucha, usted puede pasar null como la dirección ip en este caso el anfitrión escuchara todas las interfaces de network (red). El servidor puede soportar solamente un Websocket Host y al mismo tiempo, puede manejar anfitriones genéricos también:
NetworkTransport.AddWebsocketHost(topology, 8887, null);
NetworkTransport.AddHost(topology, 8888);
Abrirá un socket tcp que maneja un protocolo socket web en puerto 8887 y un socket udp manejando un protocol genérico en puerto 8888.