1. 程式人生 > >unity開發:TCP socket網路連線

unity開發:TCP socket網路連線

unity內部封裝了一個很高層次的網路介面,不過有時候並不需要那麼複雜的功能,只是想實現簡單的TCP網路連線,可以在unity裡面用C#寫tcp socket。

以下TCP連線是同步模式

建立兩個unity工程,編寫指令碼。

服務端

using UnityEngine;
using System.Collections;
//引入庫
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

public class TcpServer:MonoBehaviour
{
    //以下預設都是私有的成員
    Socket serverSocket; //伺服器端socket
    Socket clientSocket; //客戶端socket
    IPEndPoint ipEnd; //偵聽埠
    string recvStr; //接收的字串
    string sendStr; //傳送的字串
    byte[] recvData=new byte[1024]; //接收的資料,必須為位元組
    byte[] sendData=new byte[1024]; //傳送的資料,必須為位元組
    int recvLen; //接收的資料長度
    Thread connectThread; //連線執行緒

    //初始化
    void InitSocket()
    {
        //定義偵聽埠,偵聽任何IP
        ipEnd=new IPEndPoint(IPAddress.Any,5566);
        //定義套接字型別,在主執行緒中定義
        serverSocket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
        //連線
        serverSocket.Bind(ipEnd);
        //開始偵聽,最大10個連線
        serverSocket.Listen(10);

        
             
        //開啟一個執行緒連線,必須的,否則主執行緒卡死
        connectThread=new Thread(new ThreadStart(SocketReceive));
        connectThread.Start();
    }

    //連線
    void SocketConnet()
    {
        if(clientSocket!=null)
            clientSocket.Close();
        //控制檯輸出偵聽狀態
        print("Waiting for a client");
        //一旦接受連線,建立一個客戶端
        clientSocket=serverSocket.Accept();
        //獲取客戶端的IP和埠
        IPEndPoint ipEndClient=(IPEndPoint)clientSocket.RemoteEndPoint;
        //輸出客戶端的IP和埠
        print("Connect with "+ipEndClient.Address.ToString()+":"+ipEndClient.Port.ToString());
        //連線成功則傳送資料
        sendStr="Welcome to my server";
        SocketSend(sendStr);
    }

    void SocketSend(string sendStr)
    {
        //清空傳送快取
        sendData=new byte[1024];
        //資料型別轉換
        sendData=Encoding.ASCII.GetBytes(sendStr);
        //傳送
        clientSocket.Send(sendData,sendData.Length,SocketFlags.None);
    }

    //伺服器接收
    void SocketReceive()
    {
        //連線
        SocketConnet();      
        //進入接收迴圈
        while(true)
        {
            //對data清零
            recvData=new byte[1024];
            //獲取收到的資料的長度
            recvLen=clientSocket.Receive(recvData);
            //如果收到的資料長度為0,則重連並進入下一個迴圈
            if(recvLen==0)
            {
                SocketConnet();
                continue;
            }
            //輸出接收到的資料
            recvStr=Encoding.ASCII.GetString(recvData,0,recvLen);
            print(recvStr);
            //將接收到的資料經過處理再發送出去
            sendStr="From Server: "+recvStr;
            SocketSend(sendStr);
        }
    }

    //連線關閉
    void SocketQuit()
    {
        //先關閉客戶端
        if(clientSocket!=null)
            clientSocket.Close();
        //再關閉執行緒
        if(connectThread!=null)
        {
            connectThread.Interrupt();
            connectThread.Abort();
        }
        //最後關閉伺服器
        serverSocket.Close();
        print("diconnect");
    }

    // Use this for initialization
    void Start()
    {
        InitSocket(); //在這裡初始化server
    }


    // Update is called once per frame
    void Update()
    {

    }

    void OnApplicationQuit()
    {
        SocketQuit();
    }
}
  • 建立套接字
  • 繫結套接字到ip和埠
  • 偵聽連線
  • 接收連線
  • 與客戶端收發資料
  • 返回等待另一連線
  • 斷開連線
把指令碼掛到unity場景中某個物體上,比如camera,由於建立連線後有接收迴圈,所以要單獨開一個執行緒,否則主執行緒會卡死。 客戶端
using UnityEngine;
using System.Collections;
//引入庫
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

public class TcpClient:MonoBehaviour
{
    string editString="hello wolrd"; //編輯框文字

    Socket serverSocket; //伺服器端socket
    IPAddress ip; //主機ip
    IPEndPoint ipEnd; 
    string recvStr; //接收的字串
    string sendStr; //傳送的字串
    byte[] recvData=new byte[1024]; //接收的資料,必須為位元組
    byte[] sendData=new byte[1024]; //傳送的資料,必須為位元組
    int recvLen; //接收的資料長度
    Thread connectThread; //連線執行緒

    //初始化
    void InitSocket()
    {
        //定義伺服器的IP和埠,埠與伺服器對應
        ip=IPAddress.Parse("127.0.0.1"); //可以是區域網或網際網路ip,此處是本機
        ipEnd=new IPEndPoint(ip,5566);
        
        
        //開啟一個執行緒連線,必須的,否則主執行緒卡死
        connectThread=new Thread(new ThreadStart(SocketReceive));
        connectThread.Start();
    }

    void SocketConnet()
    {
        if(serverSocket!=null)
            serverSocket.Close();
        //定義套接字型別,必須在子執行緒中定義
        serverSocket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
        print("ready to connect");
        //連線
        serverSocket.Connect(ipEnd);

        //輸出初次連線收到的字串
        recvLen=serverSocket.Receive(recvData);
        recvStr=Encoding.ASCII.GetString(recvData,0,recvLen);
        print(recvStr);
    }

    void SocketSend(string sendStr)
    {
        //清空傳送快取
        sendData=new byte[1024];
        //資料型別轉換
        sendData=Encoding.ASCII.GetBytes(sendStr);
        //傳送
        serverSocket.Send(sendData,sendData.Length,SocketFlags.None);
    }

    void SocketReceive()
    {
        SocketConnet();
        //不斷接收伺服器發來的資料
        while(true)
        {
            recvData=new byte[1024];
            recvLen=serverSocket.Receive(recvData);
            if(recvLen==0)
            {
                SocketConnet();
                continue;
            }
            recvStr=Encoding.ASCII.GetString(recvData,0,recvLen);
            print(recvStr);
        }
    }

    void SocketQuit()
    {
        //關閉執行緒
        if(connectThread!=null)
        {
            connectThread.Interrupt();
            connectThread.Abort();
        }
        //最後關閉伺服器
        if(serverSocket!=null)
            serverSocket.Close();
        print("diconnect");
    }

    // Use this for initialization
    void Start()
    {
        InitSocket();
    }

    void OnGUI()
    {
        editString=GUI.TextField(new Rect(10,10,100,20),editString);
        if(GUI.Button(new Rect(10,30,60,20),"send"))
            SocketSend(editString);
    }

    // Update is called once per frame
    void Update()
    {

    }

    //程式退出則關閉連線
    void OnApplicationQuit()
    {
        SocketQuit();
    }
}
  • 建立套接字
  • 向伺服器發出連線請求
  • 和伺服器通訊
  • 斷開連線
同樣把指令碼掛到場景某個物體中,建立連線和接收迴圈都放在新開的執行緒裡面,在介面上放一個文字編輯框和一個button用於給服務端發訊息。 測試 程式實現的功能為,當一個新的客戶端連線到服務端時,服務端控制檯輸出相關資訊,並向客戶端傳送初始資訊,客戶端每次向服務端的資訊由服務端接收後新增一段字串再發送回來。