Unity實現簡單的多人聊天工具
本文實例為大傢分享瞭Unity實現多人聊天工具的具體代碼,供大傢參考,具體內容如下
代碼1 : 服務端代碼
using UnityEngine; using System.Net.Sockets; using System.Net; using System.Threading; public class ChatServer : MonoBehaviour { // 設置連接端口 const int portNo = 500; string m_ServerIP = ""; // Use this for initialization void Start () { m_ServerIP = Network.player.ipAddress;//獲取本機服務器的IP print("服務器IP:"+m_ServerIP); //開啟新的線程來執行TCP的監聽 myThread.Start (); //支持後臺運行避免最小化後不運行 Application.runInBackground = true; } private void ListenClientConnect () { Debug.Log("正在啟動服務器!"); // 初始化服務器IP IPAddress localAdd = IPAddress.Parse(m_ServerIP); // 創建TCP偵聽器 TcpListener listener = new TcpListener (localAdd, portNo); listener.Start (); Debug.Log("服務器正在運行中......."); //溫馨提示:建議使用Windows電腦運行服務器,如果是Mac系統一定要看到打印這句話服務器才啟動起來瞭,否則服務器表示沒有啟動 // 循環接受客戶端的連接請求 while (true) { //編寫各個客戶端的類,隻要監聽到有IP連接服務器,就實例化對應的客戶端 ChatClient user = new ChatClient (listener.AcceptTcpClient()); // 顯示連接客戶端的IP與端口【隻要有新的客戶端連接進來就會打印打控制臺誰進來瞭】 print (user._clientIP + " 加入服務器\n"); } } }
代碼2 : 客戶端與服務端交互
using UnityEngine; using System.Collections; using System.Net.Sockets; using System; using System.Text; //各個客戶端自身應該有的邏輯【進入服務器離開服務器等】 public class ChatClient : MonoBehaviour { static Hashtable ALLClients = new Hashtable ();// 客戶端列表 private TcpClient _client;// 客戶端實體 public string _clientIP;// 客戶端IP private string _clientNick;// 客戶端昵稱 private byte[] data;// 消息數據 private bool ReceiveNick = true;//是否從客戶端接受到他的昵稱[消息分割標識] void Awake () { Application.runInBackground = true; } //由服務器創建實例 public ChatClient (TcpClient client) { //客戶端實體對象 this._client = client; this._clientIP = client.Client.RemoteEndPoint.ToString (); // 把當前客戶端實例添加到客戶列表當中 //第一個參數時IP,第二個為對應客戶端 ALLClients.Add (this._clientIP, this); data = new byte[this._client.ReceiveBufferSize]; // 從服務端獲取消息 client.GetStream ().BeginRead (data, 0, System.Convert.ToInt32 (this._client.ReceiveBufferSize), ReceiveMessage, null); } // 從客戶端獲取消息 void ReceiveMessage (IAsyncResult ar) { int bytesRead; try { lock (this._client.GetStream()) { bytesRead = this._client.GetStream ().EndRead (ar); } //沒有讀到數據說明這個客戶端已經掉線 if (bytesRead < 1) { ALLClients.Remove (this._clientIP); //廣播 Broadcast (this._clientNick + " 已經離開服務器");//已經離開服務器 return; } else { string messageReceived = Encoding.UTF8.GetString (data, 0, bytesRead); //這個開關很關鍵,讀取到瞭發送進來的數據後,默認是收到瞭對應客戶端的昵稱的,將這個客戶端第一次發來的信息作為昵稱,以後的都是他發消息 if (ReceiveNick) { this._clientNick = messageReceived; Broadcast (this._clientNick + " 已經進入服務器");//已經進入服務器 ReceiveNick = false; } else { Broadcast (this._clientNick + ":" + messageReceived); } } lock (this._client.GetStream()) { //尾遞歸處理 this._client.GetStream ().BeginRead (data, 0, System.Convert.ToInt32 (this._client.ReceiveBufferSize), ReceiveMessage, null); } } catch (Exception ex) { ALLClients.Remove (this._clientIP); Broadcast (this._clientNick + " 已經離開服務器");//已經離開服務器 } } // 向一個客戶端發送消息 void sendMessage (string message) { try { NetworkStream ns; lock (this._client.GetStream()) { ns = this._client.GetStream (); } // 對信息進行編碼,寫入流,別忘記沖刷趕緊緩沖 byte[] bytesToSend = Encoding.UTF8.GetBytes (message); ns.Write (bytesToSend, 0, bytesToSend.Length); ns.Flush (); } catch (Exception ex) { Debug.Log ("Error:" + ex); } } // 向所有客戶端廣播消息 void Broadcast (string message) { Debug.Log (message);//打印消息 //向在服務器中連接的所有客戶端發送最新消息 foreach (DictionaryEntry c in ALLClients) { ((ChatClient)(c.Value)).sendMessage (message + Environment.NewLine); // \r是回車,英文是Carriage return 運輸返回 B位置 // \n是換行,英文是New line C位置 // Enter = 回車+換行(\r\n) 確認按鍵 D位置 //在 Windows 環境中,C# 語言 Environment.NewLine == "\r\n" // B A // D C // 當前編輯光標位置:A //機械打字機有回車和換行兩個鍵作用分別是: //換行就是把滾筒卷一格,不改變水平位置。 //回車就是把水平位置復位,不卷動滾筒。 } } }
代碼3 : 客戶端與UI交互
using UnityEngine; using System.Net.Sockets; using System; using System.Text; using UnityEngine.UI; //各個客戶端聊天的UI交互 public class ClientHandler : MonoBehaviour { const int portNo = 500; private TcpClient _client; private byte[] data; string nickName = ""; string message = ""; string sendMsg = ""; [SerializeField]InputField m_NickInput; [SerializeField]InputField m_SendMsgInput; [SerializeField]Text m_ShowMessageText; [SerializeField] InputField m_IPInput; void Update () { nickName = m_NickInput.text; m_ShowMessageText.text = message; sendMsg = m_SendMsgInput.text; } //連接服務器按鈕 public void ConBtnOnClik () { if (m_IPInput.text != "" || m_IPInput.text != null) { //真正的當前客戶端 this._client = new TcpClient(); //連接服務器的IP和端口 this._client.Connect(m_IPInput.text, portNo); //獲取緩沖區的位元組數目,即緩存區的大小 data = new byte[this._client.ReceiveBufferSize];//避免去去死,比如有些同志寫成1024 //點擊瞭連接服務器按鈕後就將昵稱也發送過去 SendMyMessage(nickName); //當前客戶端開始去讀取數據流 this._client.GetStream() .BeginRead(data, 0, System.Convert.ToInt32(this._client.ReceiveBufferSize), ReceiveMessage, null); } else { Debug.Log("請輸入正確的IP"); } } //發送消息按鈕 public void SendBtnOnClik () { //每次將輸入消息發送到服務器,並制空輸入框 SendMyMessage (sendMsg); m_SendMsgInput.text = ""; } /// <summary> /// 向服務器發送數據(發送聊天信息) /// </summary> /// <param name="message"></param> void SendMyMessage (string message) { try { NetworkStream ns = this._client.GetStream (); //因為我們現在隻做文本信息的傳輸,所以這裡使用UTF編碼來寫入和識別 byte[] data = Encoding.UTF8.GetBytes (message); ns.Write (data, 0, data.Length); ns.Flush ();//沖刷趕緊buffer緩沖,準備下次再接受新的數據 } catch (Exception ex) { Debug.Log ("Error:" + ex); } } /// <summary> /// 接收服務器的數據(聊天信息) /// </summary> /// <param name="ar"></param> void ReceiveMessage (IAsyncResult ar) { try { //當上面的讀取方法執行完畢後,會自動回調這個方法 int bytesRead = this._client.GetStream ().EndRead (ar);//讀取完畢 if (bytesRead < 1) { //說明沒有讀取到任何信息 return; } else { //讀取到文本信息後使用UTF編碼解碼 ,並連續拼接起來 message += Encoding.UTF8.GetString (data, 0, bytesRead); } //再次去讀取信息 _client.GetStream ().BeginRead (data, 0, Convert.ToInt32 (_client.ReceiveBufferSize), ReceiveMessage, null); } catch (Exception ex) { print ("Error:" + ex); } } }
以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。