传输层是操作系统基于套接字的网络之上的一个层。它能够发送和接收表示为字节数组的消息,并提供许多不同的“服务质量”选项,以适应不同的场景。它专注于灵活性和性能,并在UnityEngine.Networking.NetworkTransport类中公开一个API。

    传输层支持网络通信的基础服务。这些基础服务包括:

    传输层可以使用两种协议:用于通用通信的UDPWebGLWebSockets。要直接使用传输层,典型的工作流程如下:

    1. 1、初始化网络传输层
    2. 2、配置网络拓扑
    3. 3、创建主机
    4. 4、开始通信(处理连接和发送/接收消息)
    5. 5、使用后关闭库。
    6. 6、初始化网络传输层

    初始化网络传输层时,您可以选择默认的初始化,没有参数,也可以提供控制网络层整体行为的参数,例如最大数据包大小和线程超时限制。

    1. // Initializing the Transport Layer with no arguments (default settings)
    2. NetworkTransport.Init();
    1. // An example of initializing the Transport Layer with custom settings
    2. GlobalConfig gConfig = new GlobalConfig();
    3. gConfig.MaxPacketSize = 500;
    4. NetworkTransport.Init(gConfig);

    在上面的第二个示例中,传输层使用指定为500的自定义“MaxPacketSize”值进行初始化。只有在具有异常网络环境并熟悉所需的特定设置时,才应使用自定义初始值。作为一个经验法则,如果您正在开发一个典型的多人游戏,旨在通过互联网播放,默认的Init()设置,无参数应该是适当的。

    下一步是配置对等体之间的连接。您可能需要定义几个通信通道,每个通道具有指定的不同服务质量级别,以适应您要发送的特定消息类型,以及它们在游戏中的相对重要性。

    在上面的例子中,我们定义了两个具有不同服务质量值的通信通道。“QosType.Reliable”将传递消息并确保消息被传递,而“QosType.Unreliable”将发送消息没有任何保证,但会更快地做到这一点。

    网络配置的最后一步是拓扑定义。网络拓扑定义允许多少连接以及使用什么连接配置:

    1. HostTopology topology = new HostTopology(config, 10);

    这里我们创建了最多可以连接10个的拓扑,每个连接将通过上一步中定义的参数进行配置。

    正如所有初步步骤所做,我们可以创建主机(开放套接字):

    1. int hostId = NetworkTransport.AddHost(topology, 8888);

    这里我们在端口8888和任何IP地址上添加新主机。该主机最多支持10个连接,每个连接将具有我们在config对象中定义的参数。

    主机创建后,我们可以开始我们的沟通。为了做到这一点,我们发送不同的命令给主机并检查其状态。有3个主要命令可以发送:

    1. connectionId = NetworkTransport.Connect(hostId, "192.16.7.21", 8888, 0, out error);
    2. NetworkTransport.Disconnect(hostId, connectionId, out error);
    3. NetworkTransport.Send(hostId, connectionId, myReiliableChannelId, buffer, bufferLength, out error);

    1、第一个命令将使用ip“192.16.7.21”和端口8888向对等体发送连接请求。它将返回分配给此连接的ID。2、第二个将发送断开连接请求,3、第三个将发送消息,与id相等的连接connectionId,使用id相等的可靠信道myReiliableChannelId,消息应存储在buffer[]该消息的长度上,由消息的长度定义bufferLength。

    要检查主机状态,您可以使用两个功能:

    1. {
    2. int recHostId;
    3. int connectionId;
    4. int channelId;
    5. byte[] recBuffer = new byte[1024];
    6. int bufferSize = 1024;
    7. int dataSize;
    8. byte error;
    9. NetworkEventType recData = NetworkTransport.Receive(out recHostId, out connectionId, out channelId, recBuffer, bufferSize, out dataSize, out error);
    10. switch (recData)
    11. {
    12. case NetworkEventType.Nothing: //1
    13. break;
    14. case NetworkEventType.ConnectEvent: //2
    15. break;
    16. case NetworkEventType.DataEvent: //3
    17. break;
    18. case NetworkEventType.DisconnectEvent: //4
    19. break;
    20. }
    21. }

    • 要点1:没有返回任何有趣的事件。• 要点2:连接事件进来,它可以是新的连接,也可以是以前的连接命令响应:

    1. myConnectionId = NetworkTransport.Connect(hostId, "192.16.7.21", 8888, 0, out error);
    2. switch (recData)
    3. case NetworkEventType.ConnectEvent:
    4. if(myConnectionId == connectionId)
    5. //my active connect request approved
    6. else
    7. //somebody else connect to me
    8. break;
    9. //...
    10. }

    • 要点3:收到数据。在这种情况下recHostId将定义主机,connectionId将定义连接,channelId将定义通道; dataSize将定义接收到的数据的大小。如果recBuffer足够大以容纳数据,数据将被复制到缓冲区中。如果没有,error将包含MessageToLong错误,您将需要重新分配缓冲区并再次调用此函数。

    • 要点4:断线信号进入,可能是建立连接断开或连接请求失败的信号。

    1. myConnectionId = NetworkTransport.Connect(hostId, "192.16.7.21", 8888, 0, out error);
    2. NetworkEventType recData = NetworkTransport.Receive(out recHostId, out connectionId, out channelId, recBuffer, bufferSize, out dataSize, out error);
    3. switch (recData)
    4. {
    5. case NetworkEventType. DisconnectEvent:
    6. if(myConnectionId == connectionId)
    7. //cannot connect by some reason see error
    8. else
    9. //one of the established connection has been disconnected
    10. break;
    11. \\...
    12. }

    客户端上的WebSocket已被支持。对于客户端,上述所有步骤(包括拓扑和配置)应该相同。Web客户端只能连接到服务器,其中服务器是独立播放器(仅限Win,Mac或Linux)。在服务器上,你应该打电话

    在ip地址是侦听地址的地方,你可以通过null作为ip地址,在这种情况下主机将监听所有的网络接口。服务器只能支持一个Websocket主机,同时也可以处理通用主机:

    1. NetworkTransport.AddHost(topology, 8888);

    将打开tcp套接字处理端口8887上的Web套接字协议和udp套接字处理端口8888上的基因协议。

    ?