2017年11月10日 星期五

Unity內使用UDP方式來進行連線和傳送資料

網路連線、TCP和UDP那些大道理就不講了,不懂的人建議在看這篇前先去觀看一下相關的定義。

這邊簡單來講,有兩個程式分別在兩台電腦上,希望可以透過網路來互相傳遞資料,因此其中之一的作法便是透過UDP方式來進行傳送資料。

可以分開寫成兩個程式,也可以全部都寫在同一個程式內,然後自己再另外寫可選擇當Server或Client的程式。我是常常寫在一個程式內,然後再外加可選擇的方式來定義Server和Client。

所以以下單純來看Script,有Server和Client的Script。

先來看當Client的Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.Net.Sockets;

public class ClientController : MonoBehaviour {

    private IPEndPoint ipEndPoint;
    private UdpClient udpClient;
    private byte[] sendByte;

    void Start ()
    {
        ipEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5555);
        udpClient = new UdpClient();
        SendUDPData("這是要傳送的資料");
    }

    void Update ()
    {

    }

    void SendUDPData(string tempData)
    {
        sendByte = System.Text.Encoding.UTF8.GetBytes(tempData);
        udpClient.Send(sendByte, sendByte.Length, ipEndPoint);
    }
}
這邊範例的IPAddress是使用Local端,當然也可以使用網際網路的網址。
仔細看程式碼的話,便會知道Client單方面的向Server發送了資料。

再來看當Server的Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System.Threading;

public class ServerController : MonoBehaviour {

    private IPEndPoint ipEndPoint;
    private UdpClient udpClient;
    private Thread receiveThread;
    private byte[] receiveByte;
    private string receiveData = "";

    void Start ()
    {
        ipEndPoint = new IPEndPoint(IPAddress.Any, 5555);
        udpClient = new UdpClient(ipEndPoint.Port);

        receiveThread = new Thread(ReceiveData);
        receiveThread.IsBackground = true;
        receiveThread.Start();
    }

    void Update ()
    {

    }

    void ReceiveData()
    {
        while (true)
        {
            receiveByte = udpClient.Receive(ref ipEndPoint);
            receiveData = System.Text.Encoding.UTF8.GetString(receiveByte);

            Debug.Log("接收到:" + receiveData);
        }
    }

    private void OnDisable()
    {
        udpClient.Close();
        receiveThread.Join();
        receiveThread.Abort();
    }

    private void OnApplicationQuit()
    {
        receiveThread.Abort();
    }
}
可以看到Server的接收是寫在Thread裡面,如果不另外開執行緒來進行資料的監聽接收,那程式會卡死在那不會動,這點很重要。

關閉程式時,一定要徹底關閉這個Thread;不然即使程式關閉了,這個Thread還會依然持續執行,相關資訊可自行上網查詢。

這裡寫的是Client發送資料給Server的單方向範例,當然也可以Server發送資料給Client,寫法完全一樣。

因為我想要最直接呈現UDP的寫法,所以相關安全措施大都沒有加入,像Try catch等這些安全機制其實是應該要加入的。