0.前言
使用C#和Unity實現復刻Liar’s bar中的功能
軟件開發大作業
本系列文章用于記錄與分享開發過程中使用到的知識點,以及常見錯誤
本文主要描述有關網絡編程的內容
目錄
- 0.前言
- 1.使用Socket搭建Server
- 1.1Server端的Socket連接
- 1.2 Server端接收Client的信息
- 1.3 Server端接收信息后,處理信息
- 1.4 Server端給Client端發送信息
- 1.5 小結
- 2.Client端 搭建Socket連接
- 2.0 前言
- 2.1 連接服務器
- 2.2 Unity中怎么轉換Json
- 3.遠程聯機
- 3.1SakuraFrp
- 3.2 Client端
1.使用Socket搭建Server
1.1Server端的Socket連接
public static void waitClient{//ipv4地址,此處使用localhoststring host = "127.0.0.1";//端口號,需要與其他端口占用不同,例如3306,8080等//client端與此處端口相同即可string port = "6657";//創建ipIPEndPoint pos = new IPEndPoint(IPAddress.Parse(host), port);Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);listener.Bind(pos);//最多接收3個人的連接,參數可以改變listener.Listen(3);Socket sclient;String name;byte[] buffer = new byte[1024];Player p;int len;//監聽客戶端的連接while (true){//接收到客戶端連接 保存到sclient對象中sclient = listener.Accept();//并給這個對象單獨開一個監聽線程,在文后會再詳細說明Thread listen = new Thread(new ParameterizedThreadStart(listenerClient));listen.Start(sclient);}
}static void Main(String[] args){//為等待客戶端連接創建一個線程Thread wait = new Thread(new ThreadStart(waitClient));wait.Start();
}
1.2 Server端接收Client的信息
static void listenerClient(Socket s){byte[] buffer = new byte[1024];while (true){Message msg;try{int len = s.Receive(buffer);string str = Encoding.UTF8.GetString(buffer, 0, len);//根據&進行分割//由于客戶端和服務端發送信息有延遲,//傳輸時在每個信息后面加&可以分清楚信息的范圍foreach (string s in str.Split('&')){if (s.Length > 0){//反序列成msg對象 發送的是json格式的數據//這里用的是NewtonSoft.Json可以在NuGet引入依賴msg = JsonConvert.DeserializeObject<Message>(s);//將msg加入到queue中//上鎖 使線程同步//這里的toDoListLock的聲明為
//private static readonly object toDoListLock = new object();lock (toDoListLock){//這里的toDoList的聲明為:
//private static Queue<Message> toDoList = new Queue<Message>();toDoList.Enqueue(msg);}}}}catch (SocketException){//常見try-catch,不做過多贅述break;}}}
//常見Msg類
class Message
{public String type;public String info;//構造器public Message(string type, string info){this.type = type;this.info = info;}
}
1.3 Server端接收信息后,處理信息
//也需要給本類啟動一個線程,
//Thread toDo = new Thread(new ThreadStart(toDoListClient));
//toDo.startstatic void toDoListClientOperation(){while (true){//循環監聽,如果此時隊列中無信息就進入下次循環if (toDoList.Count == 0){continue;}//得到msg對象Message msg = toDoList.Dequeue();switch(msg.type){//根據類型進行對應操作即可 此處省略}}}
1.4 Server端給Client端發送信息
static void sendMsg(string type, string info,Socket socket){Message msg = new Message(type, info);string str = JsonConvert.SerializeObject(msg);//將json字符串轉成字符數組并最后加上一個&//添加&的原因已在1.2中說明,此處省略byte[] bytes = Encoding.UTF8.GetBytes(str + '&');//發送信息socket.Send(bytes);}
1.5 小結
大體思路就是一個線程用于接收Client的連接,一個線程用于接收Client的信息,一個線程專門用于處理信息
面對Server端要被多個Client端連接時,可以創建數組保存這些Socket
2.Client端 搭建Socket連接
2.0 前言
由于Client端與Server端搭建類似,此處只寫如何連接,后面的收發信息則不過多贅述
2.1 連接服務器
//與Server端保持一致
string host = "127.0.0.1";
string port = "6657";
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(host, port);
2.2 Unity中怎么轉換Json
在Unity項目中引入NewtonSoft.Json.dll后發現經常會導致程序崩潰,
Unity中自帶一個處理JSON的類:JsonUtility 類
常用API:
JsonUtility.ToJson(param)
JsonUtility.FromJson<>(param)
3.遠程聯機
這里簡單提供一種思路:內網穿透
在代碼實現方面與上面相同,只不過host和port要改變
3.1SakuraFrp
這里用SakuraFrp實現內網穿透
搭建時本機IP去看當前聯網的屬性中IPV4的地址
(注意:此時開啟服務器的電腦本地IP不是127.0.0.1,要去Wlan那里看具體的ip是什么)
搭建選擇TCP
附SakuraFrp的官方地址:https://www.natfrp.com/
Server端的ip填寫ipv4的地址,端口就寫搭建時開放的端口
(注:Server端電腦的端口應該設置為開放)
筆者曾使用該軟件進行游戲聯機,所以想到這里能用(doge)
3.2 Client端
啟動SakuraFrp該隧道后,在日志信息中會給出映射的ip和端口
冒號前面是host,后面是port。
則Client端的host=“211.149.167.185”,port=28821