Unity3D-network網絡相關(一)

首先:Unet技術

Unity5.1爲開發者發佈全新的多玩家在線工具、技術和服務。該技術的內部項目名稱爲 UNET,全稱爲 Unity Networking。
第一階段是多玩家在線技術基礎。
第二階段基於第一階段,藉助模擬服務器引入服務器權威遊戲 (server authoritative gaming) 概念。
第三階段是最後階段,我們想通過主模擬服務器賦予協調多個模擬服務器的能力。

爲什麼我們說第一階段是多玩家在線技術基礎?主要特徵如下:

  1. 基於 UDP 的高性能傳輸層支持所有的遊戲類型
  2. 底層 API (LLAPI) 通過類似套接字的接口提供全面控制
  3. 高層 API (HLAPI) 提供簡單、安全的客戶端/服務器網絡模型
  4. 匹配服務提供基本功能,讓一個用戶創建多人模式並允許他人加入
  5. 中繼服務器解決連接問題,以便玩家在使用防火牆的情況下能相互連接

既然我們的目標是支持一切遊戲類型和任意數量的連接,我們首先開發基於 UDP 的新型高性能傳輸層。儘管使用 TCP 可以很好地開發出很多遊戲,快速動作遊戲需要使用 UDP,因爲如果數據包不按次序到達的話,TCP 會截留最近收到的數據包。
在這個新的傳輸層的基礎上,我們建立了兩個新的 API。高層 API (HLAPI) 提供簡單、安全的客戶端/服務器網絡模型。有些用戶需要較底層的訪問權限,以便實現更大的控制權限。於是,我們採用底層 API (LLAPI) 爲傳輸層提供一個更加類似於套接字的接口。如果您是網絡工程師,需要定義自定義網絡模型或需要微調網絡性能,LLAPI 將會符合您的興趣。

有了 HLAPI,就不再需要有豐富的網絡知識。而如果您是網絡工程師,想以自己的方式解決問題,則 LLAPI 可以幫得上忙。

一、非授權服務器:

不控制客戶端各個玩家做什麼即玩家輸入與輸出。客戶端發送一個確定的行爲結果到服務器,服務器端同步玩家的操作狀態到遊戲世界中,不對客戶端進行影響。

1、網絡通信方式

網絡通信兩種重要的方法:遠程函數調用和狀態同步

01、遠程過程調用

RPC(Remote Procedure Calls) 用來調用遠程計算機上某個函數的方法。
****這裏面有兩個方面:****
01、可以從客戶端調用服務器端上的某個函數
02、從服務器端調用****所有客戶端****或者某個****特定客戶端****的函數

02、狀態同步

什麼時狀態同步?就是同步各個客戶端不斷改變的數據。其實就是不斷分發玩家的狀態數據,這個過程消耗大量的帶寬,所以我們要優化帶寬數量。

二、Hight Level API(HLAPI)

就是Unity創建多人遊戲的一個功能系統,依賴較低級別的實時通信層的傳輸服務,被用來處理多人遊戲所需的許多常見服務。
HLAPI:是一個權威的服務器系統。傳輸層支持任意形式網絡拓撲結構?(可以查看我的博客:http://www.jianshu.com/p/45f8df69a743 (計算機網絡)),允許同時作爲客戶端或服務器端,所以不需要搭建專用的服務器。

客戶端作爲服務器端

 

因爲我們的角色都是專屬的,所以有MyPlayer的概念,所以當添加一個玩家對象和鏈接把它們連接起來的時候,這個Player就是該玩家客戶端的LocalPlayer.

• 使用 “Network Manager”.控制遊戲的網絡狀態。
• 主機是一個 player 客戶端。運營 “Network Manager”.遊戲
• 使用通用的序列化程序的數據進行序列化。
• 發送和接收messages郵件。
• 將網絡的命令從客戶端發送到服務器。
• 遠程過程調用 (Rpc) 從服務器向客戶端。
• 將網絡的事件從服務器發送到客戶端。

案例:

01-導入資源包:

角色資源包

02-創建我們的場景,如下圖所示,分別保存爲兩個場景:scene01,scene02

Scene01

03-新建NetWorkManager對象來管理網絡連接面板

NetWorkManager:是一個管理網絡狀態的多人遊戲的一個組成部分

Paste_Image.png

player object 被被生成是由 NetworkManager.OnServerAddPlayer 默認實現。 如果你想自定義 player object 的創建的方式,你可以重寫的虛函數。

 

  public virtual void OnServerAddPlayer(NetworkConnection conn, short playerControllerId)
    {
       var player = (GameObject)GameObject.Instantiate(playerPrefab, playerSpawnPos, Quaternion.identity);
      NetworkServer.AddPlayerForConnection(conn, player, playerControllerId);
    }

網絡管理器 具有用於輸入每一種模式的方法。
NetworkManager.StartClient()
NetworkManager.StartServer()
NetworkManager.StartHost()
是所有可用的腳本代碼,所以它們可以被調用,從鍵盤輸入的處理程序或自定義UI 事件 。
networkAddress網絡地址和 networkPort網絡端口 屬性被 使用。當啓動時後的服務器 或主機 時,networkPort 成爲偵聽端口。
當客戶端啓動時,networkAddress是要連接到的地址、networkPort 是要連接到的端口。

NetWorkManangerHUD:運行是顯示UI

Paste_Image.png

04-製作遊戲角色,保存爲預製物

添加第一人稱控制器

Paste_Image.png

Paste_Image.png

添加標示對象在網絡中的位置與同步網絡對象的位置組件

NetWorkIdentity :標示遊戲對象在網絡中的位置

Paste_Image.png

NetWorkTransform:同步網絡對象

Paste_Image.png

當網絡停止時,通過停止的服務器或主機,或斷開連接,客戶端將加載offline脫機的場景。斷開多人遊戲時遊戲允許自動返回到菜單場景 。

通過調用 NetworkManager.ServerChangeScene(),遊戲處於活動狀態時,還可以更改場景。這將使所有當前連接的客戶端更改場景,並將更新 networkSceneName,新客戶還將加載新的場景。

雖然網絡的場景管理處於活動狀態,調用任何遊戲狀態管理功能 NetworkManager.StartHost() 或 NetworkManager.StopClient() 可導致場景變化。這適用於運行時控制 UI。所以通過設置場景 並調用這些函數很容易控制流的多人遊戲。

05-同步方法1

編譯windows客戶端,會發現我們的位移在同步,因爲我們創建了兩個遊戲對象,也就存在兩個相機,所以我們需要控制他們

 

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class Player_NetworkStep : NetworkBehaviour {

    public Camera firstControllerCamera;
    public AudioListener lister;
    void Start () {
        if (isLocalPlayer) // 判斷是否是本地遊戲對象
        {
            GameObject.FindWithTag("MainCamera").SetActive(false);
            GetComponent<CharacterController>().enabled = true;
            GetComponent<UnityStandardAssets.Characters.FirstPerson.FirstPersonController>().enabled = true;
            firstControllerCamera.enabled = true;
            lister.enabled = true;
        }
    }   
}

Paste_Image.png

06-同步方法2

1、刪除我們的NetworkTransform,也就是不同步我們的位置消息,我們自己寫腳本來同步

 

300

 

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

// 必須繼承NetWorkBehaviour
public class Player_NetworkStep : NetworkBehaviour {
    [SyncVar] // 用來標記同步成員變量,可以是任何基本數據類型,但不能是類、列表或其他集合
    Vector3 synsPos;
    public Transform myTransform;
    public float lerpRate = 15;

    void FixedUpdate()
    {
        TransmitPosition();
        LerpPosition();
    }

    void LerpPosition()
    {
        if (!isLocalPlayer)
        {
            myTransform.position = Vector3.Lerp(myTransform.position, synsPos, Time.deltaTime);
        }
    }
    [Command] // 新的網絡系統中的RPC,即在客戶端調用,在服務器執行。還有一種是ClientRpcCalls,正好相反
    void CmdProvidePositionToServer(Vector3 pos) // 方法以Cmd開頭,使用此命令的任意參數都會被傳遞到服務器端
    {
        synsPos = pos;
    }

    [ClientCallback] // 可作爲成員函數的自定義屬性
    void TransmitPosition()
    {
        if (isLocalPlayer)
        {
            CmdProvidePositionToServer(myTransform.position);
        }
    }

07-知識點:

網絡系統 具有網絡中執行操作actions 的方法。這些類型的actions 有時是調用遠程過程調用(Remote Procedure Calls)。在網絡系統中有兩種類型的 Rpc :

1、Command 命令- 從客戶端調用 和 運行在服務器上。
如果需要創建一個 Command函數,需要添加[Command]自定義屬性且函數必須以以Cmd開頭,當這個函數在客戶端連接的時候,函數的功能將在服務器端實現,使用此命令的任意參數都會被傳遞到服務器端
Command命令每幀都會從客戶端向服務器發送命令,這一行爲會產生大量的網絡通信量。

 

Cmd

 

默認從可靠的0通道發送命令,所以在默認情況下使用很可靠。可以通過Channel調用

 

[Command(channel=1)]

2、ClientRpc calls - 在服務器上調用 在 客戶端上運行。
可以從任何服務器對象發送,一個已經產生了的 NetworkIdentity 。因爲服務器具有authority授權,然後沒有安全性方面的問題,服務器對象能夠發送這些調用。它在服務器上調用時,此函數將運行在客戶端上。任何參將數自動傳遞給 ClientRpc 調用客戶端。
使用ClientRpc的時候也需要首方法寫Rpc開頭,此函數在服務器端調用,將在客戶端執行其功能。

 

Rpc

 

當作爲一個 LocalClient 的主機遊戲運行時, ClientRpc 將被將被LocalClient調用 -,即使它是在相同的服務器進程。所以 LocalClients 和 RemoteClients 的行爲是相同的, 對於ClientRpc 調用。

Paste_Image.png

[SyncVar]
用來標記同步成員變量,可以是任何基本數據類型,但不能是類、列表或其他集合

Paste_Image.png

[ClientCallback]:NetworkBehaviour中成員函數的自定義屬性,可以通過自定義屬性來指定函數只作爲服務器端函數或客戶端函數

 

    [Client] // 只作用在客戶端
    [Server] // 只作用在服務器端
    [ClientCallback] // engine調用函數,只在客戶端執行

Paste_Image.png

08-保存場景出現問題解決辦法:

一般情況斷網與聯網不在一個場景中,所以我們要設置上次保存的場景。將Main場景中的NetWorkManager控件Copy到Menu中,設置其中的OffineScene和OnlineSecene爲scene01(斷網場景)和scene02(連網場景),隨後刪除scenes02中的NetworkManager

同時控制我們遊戲角色對象的Cube使其跟隨Carema的方向變化而改變

 

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
using System;

public class Player_syncRotation : NetworkBehaviour {

    [SyncVar]
    private Quaternion syncPlayerRotion;
    [SyncVar]
    private Quaternion syncCamRotation;
    [SerializeField]
    private Transform playerTrans;
    private Transform camTransform;
    private float lerpRate = 15;


    void FixedUpdate()
    {
        TransmitRotation();
        LerpRotation();
    }

    private void TransmitRotation()
    {
      
    }

    private void LerpRotation()
    {
        if (!isLocalPlayer)
        {
            playerTrans.rotation = Quaternion.Lerp(playerTrans.rotation, syncPlayerRotion, Time.deltaTime * lerpRate);
            camTransform.rotation = Quaternion.Lerp(camTransform.rotation, syncCamRotation, Time.deltaTime * lerpRate);
        }
    }
    [Command]
    void CmdProvideRotationToServer(Quaternion playerRot, Quaternion cameRot)
    {
        syncPlayerRotion = playerRot;
        syncCamRotation = cameRot;
    }
    [Client]
    void TransmitRotion()
    {
        if (isLocalPlayer)
        {
            CmdProvideRotationToServer(playerTrans.rotation, camTransform.rotation);
        }
    }
}

添加到角色預製物上。

09-創建出生點:

Start Positions
若要控制player 被創建,在這裏,你可以使用 NetworkStartPosition 組件。網絡管理器查找場景中的 NetworkStartPosition 對象,如果它找到了,然後它將產生Player的位置和方向 。自定義代碼可以通過NetworkManager.startPositions列表 ,訪問可用的 NetworkStartPositions,也是一個 helper 函數 GetStartPosition() 對網絡管理器,可以在執行 OnServerAddPlayer 用於查找起始位置。

空物體添加子物體,在子物體添加NetworkStartPosition,多複製幾個擺好位置。

Paste_Image.png

10-讓角色移動更平滑

修改FixedUpdate更新頻率:0.02秒,打印發現Time.deltaTime = 0.02.我們是進行位置插值,所以放在我們的Update()函數中更加平滑

 

Paste_Image.png

同理也在另一個腳本進行同樣的操作:

 

Paste_Image.png

我們發現間歇有點卡頓,我們對它做修改

 

Paste_Image.png

 

// 添加他的網絡通道與網絡通信間歇
[NetworkSettings(channel = 0, sendInterval = 0.033f)]
public class Player_syncRotation : NetworkBehaviour 

三、TransPort Layer API

除了上面的簡易high Level API,Unity還提供了較低級別的傳輸層API.
TransPort Layer API:能夠發送和接受消息閉關表示爲數組的字節,還提供了大量不同的“服務端質量”,以適應不同的場景,支持基礎的網絡通信服務。簡單說:給你來點更加具有自由的網絡通信服務。
• 優化基於 UDP 協議。
• Multi-channel design to avoid head-of-line blocking issues 多通道設計,以避免頭的線阻塞問題
• 每個通道支持各種levels 的服務質量 (QoS) 。
• 靈活的網絡拓撲結構,支持對等 或 客戶機-服務器體系結構。

1、兩種協議:

01-通用通信UDP

典型工作流程
(1)初始化網絡傳輸層

 

        // 不帶參數初始化
        NetworkTransport.Init();
        // 設置最大數據包爲500
        GlobalConfig globalconfig = new GlobalConfig();
        globalconfig.MaxPacketSize = 500;
        NetworkTransport.Init(globalconfig);

(2)配置拓撲網絡

 

        ConnectionConfig config = new ConnectionConfig();
        // QosType.Reliable 可靠連接,確保信息傳輸安全
        byte reliableByteId = config.AddChannel(QosType.Reliable);
        // QosType.Unreliable 不可靠連接,傳輸速度快,不能保證信息傳遞
        byte unreliableByteId = config.AddChannel(QosType.Unreliable);
        // 網絡拓撲的定義, (連接使用配置信息,允許連接數)
        HostTopology topology = new HostTopology(config, 10);

(3)創建服務器主機

 

       // 創建主機服務(端口號:8888)
        int intHostID = NetworkTransport.AddHost(topology, 8888);

(4)開始通信

 

    private byte error;
    private byte[] buffer;
    private int bufferLength = 1024;

        // 先將不同的命令發送主機並檢查狀態
        // 返回一個給此鏈接的ID
        int connetionID = NetworkTransport.Connect(intHostID, "192.168.1.131", 8888, 0, out error);
        // 此命令發送斷開鏈接的請求
        NetworkTransport.Disconnect(intHostID, connetionID, out error);
        // 發送信息,將消息存儲在緩存區消息長度爲bufferLength
        NetworkTransport.Send(intHostID, connetionID, reliableByteId, buffer, bufferLength, out error);

// 檢測主機狀態:
void Update () {
        myConnectinID = NetworkTransport.Connect(hostId, "192.168.1.133", 8888, 0, out error);
        // 此函數返回來自任意主機的事件(recHostId返回主機ID)
        NetworkEventType recData = NetworkTransport.Receive(out recHostId, out connectionID, out reliableByteId, recbuffer, bufferSize, out dataSize, out error);
         switch(recData)
         {
            case NetworkEventType.ConnectEvent:
                if (myConnectinID == connetionID)
                {
                    // 主動連接請求成功
                }
                else {
                    // 其他人連接到我
                }
                
                break;
        }
 // 此函數爲檢測主機ID
 // NetworkTransport.ReceiveRelayEventFromHost

}   

02-用於WebGL的WebSockets

Web客戶端只能連接到服務器端,服務器端是一個獨立的Player

 

// ip爲監聽地址,爲null,將監聽所有的網路接口,服務器只支持一個WebSocket主機並在同一時間內處理常用的服務器
NetworkTransport.AddWebSocketHost(topology,port,Ip);
// 例如:
NetworkTransport.AddWebSocketHost(topolagy,8888,null);

四、NetworkView : 網絡視圖組件

多人遊戲中常用的組件,用於通過網絡共享數據的組件
使用這個組件可以定義哪個遊戲對象是同步以及如何同步。因爲它可以發起上面的兩種通信類型:遠程函數調用和狀態同步。它可以指定什麼數據被共享,那個對象被同步。
爲了使用包括狀態同步或者遠程調用等網絡的功能。開發人員必須創建一個添加了NetworkView的組件的遊戲對象

五、UNET Network Messages

除了high level facilities 的命令和 RPC 調用,還有可能將原始網絡消息進行發送。
還有一類被稱爲 MessageBase,可以擴展,使可序列化的網絡消息類。此類有讀/寫對象的序列化和反序列化功能。開發人員可以執行這些函數本身,或依賴於通過網絡系統自動被創建的代碼生成實現。

 

public abstract class MessageBase
{
// De-serialize the contents of the reader into this message
public virtual void Deserialize(NetworkReader reader) {}
// Serialize the contents of this message into the writer
public virtual void Serialize(NetworkWriter writer) {}
}
有內置message 類爲常用的網絡messages類型:

EmptyMessage
StringMessage
IntegerMessage

發送一條消息有是 Send() 函數, 在 NetworkClient、 NetworkServer 和NetworkConnection 的工作方式相同。他們把消息 Id 和消息對象從 MessageBase 派生。

 

using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Networking.NetworkSystem;
 
public class SYTest : NetworkBehaviour
{
  const short MyTestMsg = 1024;
 
  NetworkClient m_client;
 
public void SendReadyToBeginMessage(int myID)
{
    var msg = new IntegerMessage(myId);
    m_client.Send(MyTestMsg , msg);
}
 
public void Init(NetworkClient client)
{
  m_client = client;
  NetworkServer.RegisterHandler(MyTestMsg , OnServerReadyToBeginMessage);
}
 
void OnServerReadyToBeginMessage(NetworkMessage netMsg)
{
  var beginMessage = netMsg.ReadMessage<IntegerMessage>();
  Debug.Log("received OnServerReadyToBeginMessage " + beginMessage.value);
}
}

 

// 聲明一個自定義網絡message類並 使用它:注意:ScoreMessage 類沒有序列化代碼。
using UnityEngine;
using UnityEngine.Networking;
 
public class Scores : MonoBehaviour
{
    NetworkClient myClient;
 
public class MyMsgType {
public static short Score = MsgType.Highest + 1;
};
 
public class ScoreMessage : MessageBase
{
public int score;
public Vector3 scorePos;
public int lives;
}
 
public void SendScore(int score, Vector3 scorePos, int lives)
{
ScoreMessage msg = new ScoreMessage();
msg.score = score;
msg.scorePos = scorePos;
msg.lives = lives;
 
NetworkServer.SendToAll(MyMsgType.Score, msg);
}
 
// Create a client and connect to the server port
public void SetupClient()
{
myClient = new NetworkClient();
myClient.RegisterHandler(MsgType.Connect, OnConnected);
myClient.RegisterHandler(MyMsgType.Score, OnScore);
myClient.Connect("127.0.0.1", 4444);
}
 
public void OnScore(NetworkMessage netMsg)
{
ScoreMessage msg = netMsg.ReadMessage<ScoreMessage>();
Debug.Log("OnScoreMessage " + msg.score);
}
 
public void OnConnected(NetworkMessage netMsg)
{
Debug.Log("Connected to server");
}
}

六、Unet Multiplayer Lobby:專門的NetworkManager網絡管理器

可以提供Unity多人遊戲大廳(Unity Multiplayer lobby )。
它包括:
• 限制可以加入的players 的數量
• 每個客戶端支持多個players ,那麼限制每個客戶端的玩家數量
• 防止玩家遊戲in-progress時加入
• 每名player 準備好狀態,所以,遊戲開始時所有玩家都是準備好了
• 每個player 配置數據
• 當比賽結束的時候重新加入大廳
• 虛擬函數,它允許自定義邏輯來 lobby eventsGuiLobbyManager 是爲lobby 特殊lobby 管理,提供了UI 。它可以作爲一個資產包(asset package ),可以導入Unity項目輕鬆地添加一個lobby 到多人遊戲。腳本和 UI 預置在包中可以定製,爲使外觀和感覺與衆不同。有兩種player 對象- 在NetworkLobbyManager中的每個預製的插槽(prefab slot ) :
LobbyPlayer 對象
• 每個player• 創建客戶端連接,或添加player時 被創建
• 一直存在直到客戶端斷開連接
• 爲該player在大堂準備好了flag
• 在大廳裏處理命令• 將用戶腳本添加到prefab來保存特定於遊戲的玩家數據
GamePlayer 對象
• 每個player
• 當開始遊戲場景時創建
• 重新進入大廳時被摧毀
• 在遊戲中處理命令
NetworkLobbyPlayer 組件用於 LobbyPlayer 的對象。它提供了一些可用於自定義大堂行爲的虛函數回調

 

public virtual void OnClientEnterLobby()
{
}
public virtual void OnClientExitLobby()
{
}
public virtual void OnClientReady(bool readyState)
{
}

七、Internet Services : 網絡服務-多用戶服務器端

這項服務是Unity支持開發者的遊戲開發和發佈,讓開發者可以在互聯網上進行通信,爲開發者提供相關比賽創建和廣告匹配。目前已經收錢,其實就是一個網絡服務器.
Unity 提供互聯網服務,以 支持你的遊戲,在整個生產和發行,其中包括:
• Matchmaking service
• Create matches and advertise matches.
• List available matches and join matches.
• Relay server
• Game-play over internet with no dedicated server.
• Routing of messages for participants of matches.

1、使用網絡服務先創建項目ID
https://unrt.cloud.unity3d.com/

八、第三方網絡解決方案

其實除卻上面,我們還有更多選擇,可以使用第三方的網絡解決方案.
常用的有:

1-RakNet

RakNet是一個基於[UDP]網絡傳輸協議的C++網絡庫,允許程序員在他們自己的程序中實現高效的網絡傳輸服務。通常情況下用於遊戲,但也可以用於其它項目。

 

#include <stdio.h>
#include <conio.h>
#include <string.h>
#include "RakClientInterface.h" //建立客服端所需要的信息,其中包括客服端的建立,連接和數據的發送和接收
#include "RakNetworkFactory.h" //用於管理我們在程序中使用的類,包括類內存分配和類內存的釋放
#include "RakServerInterface.h" //用於建立服務器所需用的信息,包括服務器的建立,連接和數據的發送和接收
#include "PacketEnumerations.h" //用於處理網絡引擎在運行過程中得到的信息
Packet *packet;//網絡傳輸中用於存儲數據的一個數據結構
/////////////////////////////////////////////////////
/*
Struct Packet
{
PlayerID playerId; //表明了包的出處。每一個連接服務器的客戶端都將被分配一個唯一的ID號,用於標識自己。
Unsigned long length; //數據長度
Unsigned long bitsize; //比特大小
Char *data; //包中的數據
}
*/
/////////////////////////////////////////////////////
int main(void)
{
char str[512];
RakClientInterface *rakClientInterface;
RakServerInterface *rakServerInterface;
print("(C)客服端 (S)服務器?\n");
gets(str);
if (str[0]=='c')
{
//初始化一個客戶端實例,爲它分配內存
rakClientInterface=RakNetworkFactory::GetRakClientInterface();
rakServerInterface=0;
print("客服端已經建立。");
}
else
{
rakClientInterface=0;
//初始化一個服務器實例,爲它分配內存
rakServerInterface=RakNetworkFactory::GetRakServerInterface();
print("服務器已經建立。");
}
if (rakServerInterface)
{
rakServerInterface->Start(32, 0, 0, 60000);// 服務器運行在端口60000處
/*第一個參數表明你的服務器允許同時連接多少個客戶端,這個參數最大可以設置成65535;
第二個參數做保留之用,設置成0;
第三個參數用於設置多久進行服務器更新,參數要大於等於0,表示用每隔當前設置的毫秒數進行更新,這裏設置的是0;
最後一個參數用於設置服務器的端口;*/
}
else
{
// 運行客戶端
print("輸入服務器[IP地址]:\n");
gets(str);
// 127.0.0.1默認
if (str[0]==0)
strcpy(str, "127.0.0.1");
rakClientInterface->Connect(str, 60000, 0, 0, 0);
/*第一個參數表示你要連接的服務器的IP地址,如果是在自己這臺計算機調試程序,直接輸入”127.0.0.1”或“localhost
第二個參數表示要連接的服務器的端口;
第三個參數表示要連接的客戶端端口,主要就是用於客戶端之間交換數據;
第四個參數不要;
第五個參數和服務器start函數中的第三個參數一樣.*/
}
while (1)
{
if (rakServerInterface)
packet = rakServerInterface->Receive();
else
packet = rakClientInterface->Receive();
if (packet)
{
switch (packet->data[0])
{
case ID_REMOTE_DISCONNECTION_NOTIFICATION:
print("另一個連接已經斷開.\n");
break;
case ID_REMOTE_CONNECTION_LOST:
print("一個客戶端丟失連接.\n");
break;
case ID_REMOTE_NEW_INCOMING_CONNECTION:
print("一個客戶端已上線.\n");
break;
case ID_CONNECTION_REQUEST_ACCEPTED:
print("我們的連接要求已經接受.\n");
break;
case ID_NEW_INCOMING_CONNECTION:
printf("有新連接.\n");
break;
case ID_NO_FREE_INCOMING_CONNECTIONS:
printf("服務器已滿.\n");
break;
case ID_DISCONNECTION_NOTIFICATION:
if (rakServerInterface)
print("客戶端丟失.\n");
else
printf("連接中斷.\n");
break;
case ID_CONNECTION_LOST:
if (rakServerInterface)
printf("客戶端丟失連接.\n");
else
printf("連接丟失.\n");
break;
default(
printf("ID信息 %i 已經到達.\n", packet->data[0]);
break;
}
if (rakServerInterface)
rakServerInterface->DeallocatePacket(packet);
else
rakClientInterface->DeallocatePacket(packet);
}
}
// TODO - Add code body here
//getch();
if (rakClientInterface)
RakNetworkFactory::DestroyRakClientInterface(rakClientInterface);
else if (rakServerInterface)
RakNetworkFactory::DestroyRakServerInterface(rakServerInterface);
return 0;
}

特點:
1-高性能 在同一臺計算機上,RakNet可以實現在兩個程序之間每秒傳輸25,000條信息;
2-容易使用 RakNet有在線用戶手冊,視頻教程。每一個函數和類都有詳細的講解,每一個功能都有自己的例程;
3-跨平臺,當前RakNet支持Windows, Linux, Macs,可以建立在Visual Studio, GCC, Code,Blocks, DevCPP 和其它平臺上。
4-在線技術支持 RakNet有一個活躍的論壇,郵件列表,你只要給他們發信,他們可以在幾小時之內回覆你。
5-安全的傳輸 RakNet在你的代碼中自動使用SHA1,AES128, SYN,用RSA避免傳輸受到攻擊
6-音頻傳輸 用Speex編碼解碼,8位的音頻只需要每秒500字節傳輸。
7-遠程終端 用RakNet,你能遠程管理你的程序,包括程序的設置,密碼的管理和日誌的管理。
8-目錄服務器 目錄服務器允許服務器列舉他們自己需要的客戶端,並與他們連接。
9-Autopatcher Autopatcher系統將限制客戶端傳輸到服務端的文件,這樣是爲了避免一些不合法的用戶將一些不合法的文件傳輸到服務端。
10-對象重載系統
11-網絡數據壓縮BitStream類允許壓縮矢量,矩陣,四元數和在-1到1之間的實數。
12-遠程功能調用
13-強健的通信層 可以保障信息按照不同的信道傳輸

2-Photon

https://www.photonengine.com/en/OnPremise/Dashboard
是一款優秀的網絡客戶端服務器引擎,可用於與多個平臺架構,是一款實時的Socket服務器和開發框架,快速、使用方便、容易擴展
如何使用:
http://www.mamicode.com/info-detail-1219760.html
文檔下載:
http://download.csdn.net/download/a762923309/4936547
特點:
服務端架構在windows系統平臺上,採用C#語言編寫.
客戶端SDK提供了多種平臺的開發API
1、充分利用網絡帶寬
2、採用小尺寸的二進制協議,可根據需要使用有序可靠的UDP
3、直接支持常見的客戶端平臺,提供相同的工作流程
4、封裝每個客戶端平臺的網絡層模塊
5、通信跨平臺
6、使用Dictionary發送數據,無需擔心數據序列化反序列化

3-Smart Fox Server

SmartFoxServer 是專門爲Adobe Flash設計的跨平臺socket服務器,讓開發者高效地開發多人應用及遊戲. 該服務器主要用來創建多玩家遊戲。並提供強大的製作工具.
專門用於多用戶聯機遊戲開發,支持Flash/Flex/Air, Java, .Net, Unity3D, Apple iPhone 開發。
SFS Lite 此版本免費,只支持AS1.0 和 2.0 不支持AS3.0。可以迅速配置服務器,適合初學者。
其餘的服務都收費,懶得出錢.



作者:雷潮
鏈接:https://www.jianshu.com/p/a5c0844a0590
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

發佈了187 篇原創文章 · 獲贊 143 · 訪問量 78萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章