Checking out Unity’s NetworkTransport

I wrote up some code to help me understand Unity’s Transport Layer API. I created a “client” script and a “server” script. I then attached these two scripts to a Main Camera and hit Play. If you want, you can attach more than one “client” script.

llapichat

When the client connects, I can choose how big of a message to send. When the server receives a message, it then echoes it back to everyone who’s connected.

When you call AddHost, I think it’s spawning a thread that then listens to and sends on the port.

Here is my “ClientUI.cs”:

using UnityEngine;
using UnityEngine.Networking;

public class ClientUI : MonoBehaviour
{
    public void Start()
    {
        NetworkTransport.Init();

        ConnectionConfig config = new ConnectionConfig();
        reliableChannel = config.AddChannel(QosType.Reliable);
        HostTopology topology = new HostTopology(config, 1); // Only connect once
        // Do not put port since we are a client and want to take any port available to us
#if UNITY_EDITOR
        m_hostId = NetworkTransport.AddHostWithSimulator(topology, 200, 400);
#else
        m_hostId = NetworkTransport.AddHost(topology);
#endif
    }

    Rect windowRect = new Rect(500, 20, 100, 50);
    string ipField = System.Net.IPAddress.Loopback.ToString();
    string portField = "25000";
    byte reliableChannel;
    int m_hostId = -1;
    int m_connectionId;
    Vector2 scrollPos;
    string sizeField = "1000";
    string receiveLabel;
    public void OnGUI()
    {
        windowRect = GUILayout.Window(GetInstanceID(), windowRect, MyWindow, "Client Window");
    }

    void MyWindow(int id)
    {
        GUILayout.BeginHorizontal();
        GUILayout.Label("IP");
        ipField = GUILayout.TextField(ipField);
        GUILayout.Label("Port");
        portField = GUILayout.TextField(portField);
        if (GUILayout.Button("Connect"))
        {
            byte error;
            int connectionId;
            connectionId = NetworkTransport.Connect(m_hostId, ipField, int.Parse(portField), 0, out error);
            if (connectionId != 0) // Could go over total connect count
                m_connectionId = connectionId;
        }
        if (GUILayout.Button("Disconnect"))
        {
            byte error;
            bool ret = NetworkTransport.Disconnect(m_hostId, m_connectionId, out error);
            print("Disconnect " + ret + " error " + error);
        }
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal();
        GUILayout.Label("Size");
        sizeField = GUILayout.TextField(sizeField);
        if (GUILayout.Button("Send"))
        {
            byte error;
            byte[] buffer = new byte[int.Parse(sizeField)];
            // Just send junk
            bool ret = NetworkTransport.Send(m_hostId, m_connectionId, reliableChannel, buffer, buffer.Length, out error);
            print("Send " + ret + " error " + error);
        }
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();

        scrollPos = GUILayout.BeginScrollView(scrollPos, GUILayout.Height(200.0f), GUILayout.Width(400.0f));
        GUILayout.Label(receiveLabel);
        GUILayout.EndScrollView();

        GUILayout.BeginHorizontal();
        if (GUILayout.Button("Clear"))
        {
            receiveLabel = "";
        }
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();

        GUI.DragWindow();
    }

    public void Update()
    {
        if (m_hostId == -1)
            return;
        int connectionId;
        int channelId;
        byte[] buffer = new byte[1500];
        int receivedSize;
        byte error;
        NetworkEventType networkEvent = NetworkTransport.ReceiveFromHost(m_hostId, out connectionId, out channelId, buffer, 1500, out receivedSize, out error);
        if (networkEvent == NetworkEventType.Nothing)
            return;
        receiveLabel += string.Format("{0} connectionId {1} channelId {2} receivedSize {3}\n", networkEvent.ToString(), connectionId, channelId, receivedSize);
    }
}

My “ServerUI.cs”:

using UnityEngine;
using UnityEngine.Networking;
using System.Collections.Generic;
using System.Net;

public class ServerUI : MonoBehaviour
{
    public void Start()
    {
        NetworkTransport.Init();

        ConnectionConfig config = new ConnectionConfig();
        reliableChannel = config.AddChannel(QosType.Reliable);
        HostTopology topology = new HostTopology(config, 5); // Allow five connections
#if UNITY_EDITOR
        m_hostId = NetworkTransport.AddHostWithSimulator(topology, 200, 400, 25000);
#else
        m_hostId = NetworkTransport.AddHost(topology, 25000);
#endif
    }

    Rect windowRect = new Rect(20, 20, 100, 50);
    Dictionary<int, IPEndPoint> connectionDictionary = new Dictionary<int, IPEndPoint>();

    byte reliableChannel;
    int m_hostId = -1;
    Vector2 scrollPos;
    string receiveLabel;
    public void OnGUI()
    {
        windowRect = GUILayout.Window(GetInstanceID(), windowRect, MyWindow, "Server Window");
    }

    void MyWindow(int id)
    {
        scrollPos = GUILayout.BeginScrollView(scrollPos, GUILayout.Height(200.0f), GUILayout.Width(400.0f));
        GUILayout.Label(receiveLabel);
        GUILayout.EndScrollView();

        GUILayout.BeginHorizontal();
        if (GUILayout.Button("Clear"))
        {
            receiveLabel = "";
        }
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();

        GUI.DragWindow();
    }

    public void Update()
    {
        if (m_hostId == -1)
            return;
        int connectionId;
        int channelId;
        byte[] buffer = new byte[1500];
        int receivedSize;
        byte error;
        NetworkEventType networkEvent = NetworkTransport.ReceiveFromHost(m_hostId, out connectionId, out channelId, buffer, 1500, out receivedSize, out error);
        if (networkEvent == NetworkEventType.Nothing)
            return;
        receiveLabel += string.Format("{0} connectionId {1} channelId {2} receivedSize {3}\n", networkEvent.ToString(), connectionId, channelId, receivedSize);
        // If someone connected then save this info
        if (networkEvent == NetworkEventType.ConnectEvent)
        {
            string address;
            int port;
            UnityEngine.Networking.Types.NetworkID network;
            UnityEngine.Networking.Types.NodeID dstNode;
            NetworkTransport.GetConnectionInfo(m_hostId, connectionId, out address, out port, out network, out dstNode, out error);
            receiveLabel += string.Format("address {0} port {1}\n", address, port);
            connectionDictionary.Add(connectionId, new IPEndPoint(IPAddress.Parse(address), port));
        }
        else if (networkEvent == NetworkEventType.DisconnectEvent) // Remove from connection list
        {
            connectionDictionary.Remove(connectionId);
        }
        else if (networkEvent == NetworkEventType.DataEvent)
        {
            // Echo to everyone what we just received
            foreach (var pair in connectionDictionary)
            {
                NetworkTransport.Send(m_hostId, pair.Key, reliableChannel, buffer, receivedSize, out error);
            }
        }
    }
}

If this helped you out or you can think of any improvements or things I did wrong, please let me know. Thanks.

Leave a Reply

Your email address will not be published. Required fields are marked *