跳轉到內容

使用 XNA 建立遊戲/網路/網路引擎

50% developed
來自華夏公益教科書,開放世界的開放書籍

網路引擎

[編輯 | 編輯原始碼]

其他看起來有用的引擎

  • WCF - Windows 通訊基礎
  • XNA 整合
  • RakNet

其他有趣的事實和示例可以在這裡找到:http://create.msdn.com/en-US/education/catalog/?devarea=19,特別是名為網路預測的那個。

Lidgren 網路引擎

[編輯 | 編輯原始碼]

Lidgren 網路引擎是一個由 Michael Lidgren 建立的基於 .NET 的庫。它基本上可以與所有型別的 .NET 應用程式一起使用。它使用單個 UDP 套接字進行傳輸,並提供用於點對點和伺服器-客戶端連線的類。該引擎在 MIT 許可下執行,這意味著可以免費使用它。當前版本“gen3”需要 .NET 3.5 或更高版本。Lidgren 附帶一個額外的庫,其中包含一些類擴充套件方法,以便更好地支援 XNA。但是,您不能將 Lidgren 用於 Xbox 遊戲。[1]

重要類

[編輯 | 編輯原始碼]

NetPeer
NetPeer 代表本地連線點。它儲存並建立到其他對等點的連線。重要的派生類是NetServerNetClient,它們包含針對伺服器-客戶端系統的適當修改。

NetOutgoingMessage
此類的物件是您資訊的載體。要建立一個,您必須使用 NetPeer 物件的 CreateMessage() 方法。使用 Write(),您可以將所有資料放入訊息中。Write() 接受所有基本型別和物件。

NetIncomingMessage
這用於儲存有關接收訊息的資訊。除了內容,它還說明了 MessageType,它可能是與庫相關的,也可能是您傳送的資料。*MessageType 列表*

NetConnection
表示與遠端主機的連線。

如何開始

  1. 專案的網站下載最新版本。
  2. 開啟“Lidgren XNA Extensions/Lidgren XNA Extensions.sln”檔案並編譯解決方案。
  3. 將建立的 .dll 檔案複製到您的專案資料夾中,並在您的專案中引用它們。
  4. 現在,您應該能夠使用 Lidgren.Network 名稱空間。

如何建立對等點

class Program
{
    //hold the NetPeer Object as a member
    //In this example I use a server, because it is more common to work with server and clients
    private NetServer server;

    public Program()
    {
        //When initialising, create a configuration object.
        NetPeerConfiguration config = new NetPeerConfiguration("Server");

        //Setting the port, where the NetPeer shall listen. 
        //This is optional, but for a server its good to know, where it is reachable
        config.Port = 50001;
        //Create the NetPeer object with the configurations.
        server = new NetServer(config);
        //Start
        server.Start();
    }
}


如何傳送訊息

//get a message from the servers message pool
NetOutgoingMessage msgOut = server.CreateMessage();
//write your data
msgOut.Write("Some Text");
msgOut.Write((short)54);
//send the message to a client
server.SendMessage(msgOut, client, NetDeliveryMethod.ReliableOrdered);

不同的 NetDeliveryMethods 在這裡解釋。

如何接收訊息

//use local message variable
NetIncomingMessage msgIn;
//standard receive loop - loops through all received messages, until none is left
while ((msgIn = server.ReadMessage()) != null)
{
    //create message type handling with a switch
    switch (msgIn.MessageType)
    {
        case NetIncomingMessageType.Data:
            //This type handles all data that have been send by you.
            break;
        //All other types are for library related events (some examples)
        case NetIncomingMessageType.DiscoveryRequest:
            //...
            break;
        case NetIncomingMessageType.ConnectionApproval:
            //...
            break;
                    
    }
    //Recycle the message to create less garbage
    server.Recycle(msgIn);
}

可以在這裡找到所有 MessageTypes 的描述。

如何連線到伺服器
[2]第一步是啟用三個特定的訊息型別。

//for the server
serverConfig.EnableMessageType(NetIncomingMessageType.ConnectionApproval);
serverConfig.EnableMessageType(NetIncomingMessageType.DiscoveryRequest);
//for the client
clientConfig.EnableMessageType(NetIncomingMessageType.DiscoveryResponse);

初始化客戶端後,您可以搜尋伺服器。因此,您可以向 IP 地址傳送請求,或搜尋本地網路中的所有系統。

//search in local network at port 50001
client.DiscoverLocalPeers(50001);

伺服器現在已收到 DiscoveryRequest,必須由“接收訊息迴圈”處理。

case NetIncomingMessageType.DiscoveryRequest:
    NetOutgoingMessage msg = server.CreateMessage();
    //add a string as welcome text
    msg.Write("Hellooooo Client");
    //send a response
    server.SendDiscoveryResponse(msg, msgIn.SenderEndpoint);
    break;

客戶端現在已收到伺服器的 DiscoveryRequest。假設本地網路中只有一個伺服器,您可以直接連線到它。

case NetIncomingMessageType.DiscoveryResponse:
    Console.WriteLine("Server answered with: {0}", msgIn.ReadString());
    client.Connect(msgIn.SenderEndpoint);
    break;

最後一步是在伺服器端接收 ConnectionApproval 訊息並批准連線。

case NetIncomingMessageType.ConnectionApproval:
    msgIn.SenderConnection.Approve();
    break;

RakNet 是一個包含多個類以執行網路解決方案的庫,由 Jenkins Software LL 開發。它是一個跨平臺庫,適用於 C++ 和 C#。因此,它可以在所有主要平臺上使用,包括 Android 和 iOS。主要功能包括物件複製、大廳系統、安全連線、語音通訊和自動修補程式。[3]

Swig 可用於為本機 DLL 生成包裝程式碼,從而允許在 C# 中使用 RakNet。[4] Swing 生成 CXX 和 .h 檔案,這些檔案表示介面,以及 C# 專案連線到 DLL 所需的包含檔案。有關如何使用 Swig,請參閱詳細說明

重要類

[編輯 | 編輯原始碼]
RakPeerInterface
[編輯 | 編輯原始碼]

儘管 RakPeerInterface 不是一個實際的類,但它是網路通訊的主要介面,負責啟動。透過呼叫.GetInstance() 方法返回對等點例項。[5]

SocketDescriptor
[編輯 | 編輯原始碼]

一個例項描述了本地套接字,可用於啟動。[5]可以使用引數定義埠,或使用 0 自動選擇一個空閒埠。此外,如果需要,可以建立套接字描述符陣列。[6]

它代表來自另一個系統/計算機的訊息,幷包含有關訊息的資訊,例如長度、位元大小或傳送者的 ID。

===== 作為客戶端的連線 ===== [7]

using UnityEngine;
using System;
using System.Collections;
using RakNet;

public class ConnectClient {
      public static string remoteIP = 127.0.0.1;
      RakPeerInterface myClient;
      SocketDescriptor scktDist;
      //…
      void Awake() {
            myClient = RakPeerInterface.GetInstance();
            scktDist = new SocketDescriptor();
            //  Prameters: 1) max. number of connection 2) SocketDescriptor to specifie ports/addresses
            myClient.Startup(1,scktDist,1);
      }
      void OnGUI(){
      //…
      // if not yet connected
      myClient.Connect(remoteIP, 25000, “”,0);
      //…
      }
}

===== 作為伺服器的連線 ===== [8]啟動伺服器與上述說明非常類似。

public class ConnectServer  {
      public static string remoteIP = 127.0.0.1;

      public static int maxConnectionsAllowed = 4:
      public static int maxPlayersPerServer = 10;

      RakPeerInterface server;
      SocketDescriptor scktDist;
      //…
      void Awake() {
            server = RakPeerInterface.GetInstance();
            scktDist = new SocketDescriptor();
            server.Startup(maxConnectionsAllowed, 30, scktDist, 1);
            server.SetMaximumIncomingConnections(maxPlayersPerServer);
      }

}

===== 資料包的讀取 ===== [8]說明,如果資料包為 0,則沒有要讀取的內容。

public class PackageReading  {

      RakPeerInterface server;
      Packet p;
      //…
      void Reading() {

            while (true) {
                  if (p = server.Receive()) {
                             // do something terribly interesting with p...
                  }
            }

      }

}

===== 資料包的傳送 ===== [9]說明,它使用 BitStreams 建立“資料包”。

public class PackageReading  {

      RakPeerInterface peer;
      Packet p;
      //…
      void Sending() {
            MessageID useTimeStamp; // Assign this to ID_TIMESTAMP
            Time timeStamp; // Put the system time in here returned by GetTime()
            MessageID typeId; // This will be assigned to a type I've added after            ID_USER_PACKET_ENUM, lets say ID_SET_TIMED_MINE
            useTimeStamp = ID_TIMESTAMP;
            timeStamp = GetTime();
            typeId=ID_SET_TIMED_MINE;

            BitStream message = new BitStream();
            message.Write(useTimeStamp);
            message.Write(timeStamp);
            message.Write(typeId);

            message.Write("Hallo",5);

            peer = Send(BitStream * bitStream,HIGH_PRIORITY,RELIABLE,0,UNASSIGNED_SYSTEM_ADDRESS,true);
      }

}

Windows 通訊基礎

[編輯 | 編輯原始碼]

微軟的 Windows Communication Foundation (WCF) 是一個平臺或應用程式程式設計介面,它捆綁了多種技術,用於構建連線的服務或程式。微軟將其功能定義為:面向物件、互操作性、多種訊息模式、服務元資料、安全性和 AJAZ 和 REST 支援。 [10] 它支援透過 HTTP、TCP、訊息佇列等傳輸 SOAP。 WCF 需要 Windows XP SP2 或更高版本。 [11]

參考文獻

[編輯 | 編輯原始碼]

mglaeser 和 juliusse

華夏公益教科書