《Unity3D網絡遊戲實踐》(第2版)要點摘錄 – 「開端:Echo」

書名:《Unity3D網絡遊戲實踐》(第2版)

作者:羅培羽

所讀版本:機械工業出版社

Socket(套接字)

  • 兩個程序通過一個雙向的通信連接實現數據交換,連接的一端稱為一個「Socket」

  • 一個Socket包含了以下信息

    • 連接使用的協議

    • 本地主機的IP

    • 本地的協議端口

    • 遠程主機的IP

    • 遠程的協議端口

端口

  • 設備與外界通信交流的出口,每台計算機可分配0~65535個端口

  • 每個Socket連接都是從一台計算機的一個端口連接到另外一台計算機的某個端口

  • 每一個進程可以有多個Socket

    • 每個Socket通過不同端口與其他計算機連接

    • 每一條Socket連接代表本地Socket -> 本地端口 -> 網絡介質 -> 遠程端口 -> 遠程Socket的鏈路

    • 連接方與監聽方

      • 連接方使用不同端口連接(客戶端)

      • 監聽方只使用一個端口監聽(服務端)

        • 監聽方的Socket在連接方連接後產生

Socket通信流程

  • 客戶端/服務端分別創建自己的Socket對象

  • 服務端開啟監聽,等待客戶端接入

  • 客戶端連接服務器(三次握手)

  • 服務端接受連接,建立連接

  • 客戶端和服務端進行數據收發

  • 客戶端/服務端其中一方關閉連接(四次揮手)

基本Echo程序

客戶端
  • public class Echo : MonoBehaviour
    {
       Socket socket;

       public TMP_InputField reqField;
       public TMP_Text responseText;

       public void Connect()
      {
           //InterNetwork = IPV4        
           socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
           socket.Connect("127.0.0.1", 8888); //阻塞
      }

       public void Send()
      {
           //Send Req
           string sendStr = reqField.text;
           byte[] sendBytes = System.Text.Encoding.UTF8.GetBytes(sendStr);
           socket.Send(sendBytes); //阻塞

           //Receive Rsp
           byte[] readBuff = new byte[1024];
           int count = socket.Receive(readBuff); //阻塞
           string recevieStr = System.Text.Encoding.UTF8.GetString(readBuff, 0, count);
           responseText.text = recevieStr;
           socket.Close();
      }
    }
  • AddressFamily(地址族)

    • InterNetwork(IPv4)/InterNetworkV6(IPv6)

  • SocketType(套接字類型)(包括並不限於以下2種)

    • Dgram

      • 使用UDP

      • 不基於連接

      • 可與多個主機連接

      • 不可靠

    • Stream

      • 使用TCP

      • 基於連接

      • 與單個主機連接

      • 可靠

  • ProtocolType(協議)

    • TCP/UDP/RAW/……

服務端
  • using System.Net;
    using System.Net.Sockets;

    //Create Socket
    Socket listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    //Bind
    IPAddress ipAdr = IPAddress.Parse("127.0.0.1");
    IPEndPoint ipEp = new IPEndPoint(ipAdr, 8888); //綁定IP和端口
    listenSocket.Bind(ipEp);

    //Listen
    listenSocket.Listen(0);
    Console.WriteLine("Server Activated");

    while (true)
    {
       //Accept Client Connection
       Socket connectSocket = listenSocket.Accept(); //阻塞
       Console.WriteLine("Server Accept Connection");

       //Receive
       byte[] readBuff = new byte[1024];
       int count = connectSocket.Receive(readBuff);
       string readStr = System.Text.Encoding.UTF8.GetString(readBuff, 0, count);
       Console.WriteLine("Server Receive: " + readStr);

       //Send Rsp
       byte[] sendBytes = System.Text.Encoding.UTF8.GetBytes(readStr);
       connectSocket.Send(sendBytes);
    }
  • Bind:將綁定Socket綁定IP和接口,客戶端連接至該Socket時觸發監聽

  • Listen:開啟監聽等待客戶端連接

  • Accept:接受客戶端連接

  • IPAddress:指定IP地址

  • IPEndPoint:指定端口