本文实例为大家分享了Unity实现多人聊天工具的具体代码,供大家参考,具体内容如下
代码1 : 服务端代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
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 : 客户端与服务端交互
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
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交互
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
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); } } } |
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/jinxiul5/article/details/82115735