北京建站設(shè)計寫一篇軟文1000字
概述
在現(xiàn)代多人在線游戲中,穩(wěn)定且高效的網(wǎng)絡(luò)通信是確保游戲體驗的關(guān)鍵。本文將探討如何利用C#開源網(wǎng)絡(luò)通信庫PESocket來構(gòu)建一個簡單的Unity客戶端與.NET控制臺服務(wù)器之間的實時消息傳遞系統(tǒng)。通過本例,讀者不僅能夠了解PESocket的基本用法,還將學(xué)到一些關(guān)于設(shè)計跨平臺網(wǎng)絡(luò)應(yīng)用程序的最佳實踐。
1. PESocket簡介
PESocket開源項目GitHub地址:點擊跳轉(zhuǎn)
博客地址:C#開源網(wǎng)絡(luò)通信庫PESocket的使用 - PlaneZhong - 博客園 (cnblogs.com)
PESocket是一個輕量級、易于使用的網(wǎng)絡(luò)通信框架,特別適合于快速原型制作和小規(guī)模項目。它基于Socket編程模型,并提供了簡潔的API以簡化異步數(shù)據(jù)傳輸過程。
不用過多了解網(wǎng)絡(luò)通信內(nèi)部原理,只需幾行簡單的代碼,便能簡捷快速開發(fā)基于C#語言的服務(wù)器和客戶端,實現(xiàn)網(wǎng)絡(luò)通信。
2. 序列化與反序列化
為了在網(wǎng)絡(luò)間安全高效地傳輸復(fù)雜對象,PESocket采用了自定義的序列化機制。這使得任何實現(xiàn)了ISerializable
接口或標(biāo)記了[Serializable]
屬性的數(shù)據(jù)結(jié)構(gòu)都可以被直接打包成二進制流發(fā)送出去,到達目的地后再恢復(fù)為原始形式。
3. 會話管理
每個連接到服務(wù)器的客戶端都由一個獨立的PESession
實例代表,負責(zé)處理所有相關(guān)的輸入輸出操作。這種一對一的關(guān)系有助于實現(xiàn)更細粒度的安全控制及錯誤處理策略。
4. 日志記錄
良好的日志記錄習(xí)慣對于調(diào)試和維護網(wǎng)絡(luò)應(yīng)用至關(guān)重要。PESocket內(nèi)置了一套強大的日志系統(tǒng),可以根據(jù)不同級別(如信息、警告、錯誤等)記錄詳細的運行時狀態(tài)變化。
開發(fā)步驟
第一步:設(shè)置項目環(huán)境
- 創(chuàng)建一個新的Unity項目作為客戶端。
- 新建一個標(biāo)準(zhǔn)的.NET控制臺應(yīng)用程序充當(dāng)服務(wù)器角色。
- 在兩個項目中分別導(dǎo)入PESocket引用
網(wǎng)絡(luò)協(xié)議必須要去繼承自PESocket里的PEMsg
服務(wù)器里PESocket 放在網(wǎng)絡(luò)模塊
將協(xié)議里原來的引用都刪除-添加引用-找到之前生成的PESocket.dll
將原來服務(wù)器里的引用都刪除-添加引用-直接引用協(xié)議項目
第二步:定義通信協(xié)議
服務(wù)器需要與客戶端進行通信,需要一個網(wǎng)絡(luò)協(xié)議(類庫)
首先,我們需要定義一個共享的消息類,用于封裝待交換的信息。此例中我們僅包含了一個字符串字段text
,但根據(jù)實際需求可以擴展更多屬性。
// NetMsg.cs
using PENet;
using System;namespace PEProtocal
{[Serializable]public class NetMsg : PEMsg{public string text;}public class IPCfg{public const string srvIP = "127.0.0.1";public const int srvPort = 17666;}
}
第三步:編寫服務(wù)器端代碼
接下來創(chuàng)建服務(wù)器邏輯,包括初始化監(jiān)聽器以及處理來自遠程主機的各種事件。
有了ip端口信息就可以在服務(wù)器(ServerStart)里生成一個PESocket
但由于PESocket需要有一個進行網(wǎng)絡(luò)通信的Session,并且這個Session需要繼承自PESession
在服務(wù)器下創(chuàng)建一個session(類):ServerSession
ServerSession負責(zé)與客戶端進行連接
連接后需做
1.建立連接時需要有一個反饋
2.收到數(shù)據(jù)時對數(shù)據(jù)進行處理
3.斷開連接時打出一個反饋日志
using Protocal;
using PENet;/// <summary>
/// ServerSession負責(zé)與客戶端進行連接
/// </summary>
public class ServerSession:PESession<NetMsg>//PESession需要傳入網(wǎng)絡(luò)消息的類
{//建立連接protected override void OnConnected(){PETool.LogMsg("Client Connect");//PESocket里封裝好的方法SendMsg(new NetMsg{text = "Welcome to connect."});}//收到數(shù)據(jù)protected override void OnReciveMsg(NetMsg msg){PETool.LogMsg("Client Req:" + msg.text);SendMsg(new NetMsg{text = "SrvRsp:" + msg.text});}//斷開連接protected override void OnDisConnected(){PETool.LogMsg("Client DisConnect");}}
在服務(wù)器端,
ServerStart
類是整個應(yīng)用的入口點。它負責(zé)初始化網(wǎng)絡(luò)通信服務(wù),并保持服務(wù)器運行狀態(tài)以便持續(xù)監(jiān)聽來自客戶端的連接請求。?
using PENet;
using Protocal;/// <summary>
/// 服務(wù)器
/// </summary>
namespace Server
{class ServerStart{static void Main(string[] args){//需要一個進行網(wǎng)絡(luò)通信的Session,并且這個Session需要繼承自PESession,還有一個網(wǎng)絡(luò)消息的類(協(xié)議)PESocket<ServerSession, NetMsg> server = new PESocket<ServerSession, NetMsg>();server.StartAsServer(IPCfg.srvIP, IPCfg.srvPort);//需要傳遞的ip和端口while (true){/* Keep the application running */}}}
}
第四步:配置Unity客戶端
現(xiàn)在轉(zhuǎn)向Unity工程,在MonoBehaviour腳本中添加必要的邏輯以便建立與遠端服務(wù)的鏈接并發(fā)送/接收文本消息。
將協(xié)議工程導(dǎo)出(給客戶端使用)
屬性-生成 更改路徑 生成-重新生成解決方案
unity里直接導(dǎo)入PESocket與協(xié)議dll
客戶端也需要一個Session
Session 用來和客戶端進行連接,每個客戶端對應(yīng)一個session(只用關(guān)聯(lián)自己),服務(wù)器對應(yīng)多個客戶端(有多個session)??
using PENet;
using Protocal;
using UnityEngine;public class ClientSession:PESession<NetMsg>
{//建立連接protected override void OnConnected(){//PETool.LogMsg("Server Connect");//PESocket里封裝好的方法,在控制臺輸出Debug.Log("Server Connect");}//收到數(shù)據(jù)protected override void OnReciveMsg(NetMsg msg){//PETool.LogMsg("Server Rsp:" + msg.text);Debug.Log("Server Rsp:" + msg.text);}//斷開連接protected override void OnDisConnected(){//PETool.LogMsg("Server DisConnect");Debug.Log("Server DisConnect");}
}
GameStart
類,用于管理游戲?qū)ο蟮男袨檫壿嫛_@個腳本主要關(guān)注于建立與服務(wù)器的連接、配置日志記錄以及處理用戶輸入以發(fā)送消息給服務(wù)器。
using UnityEngine;
using Protocal;public class GameStart : MonoBehaviour
{PENet.PESocket<ClientSession, NetMsg> client = null;private void Start(){client = new PENet.PESocket<ClientSession, NetMsg>();client.StartAsClient(IPCfg.srvIP, IPCfg.srvPort);//啟動客戶端//指定一個日志的接口,可以把PESocket里的日志通過unity控制臺打印;//(日志是否開啟,日志的回調(diào)函數(shù)(內(nèi)容,日志的級別(?)))client.SetLog(true, (string msg, int lv) =>{switch (lv)//對不同的日志級別顯示不同的提示{case 0:msg = "Log:" + msg;Debug.Log(msg);break;case 1://警告msg = "Warn:" + msg;Debug.Log(msg);break;case 2://錯誤msg = "Error:" + msg;Debug.Log(msg);break;case 3://普通信息msg = "Info:" + msg;Debug.Log(msg);break;}});}private void Update(){if (Input.GetKeyDown(KeyCode.Space)){client.session.SendMsg(new NetMsg { text = "Hello Unity" });}}
}