Unity实现简单的多人聊天工具

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);               }        } }

推荐阅读