unity3d游戏开发之实现基于Socket通讯的公共聊天室
由于这段时间比较忙,所以也很久没发布过新的教程,这几天刚好要为一个项目写服务端程序,所以顺便也在Unity3d里面实现了一个简单的客户端,多个客户端一同使用就是一个简单的公共聊天室了。服务端为一个控制台程序使用C#实现,当然,在Unity3d中也相应地使用了C#语言实现客户端,服务端和客户端能实现消息的互通,当服务端接收到某客户端发送过来的消息时将会对客户端列表成员进行广播,这是公共聊天室的最基本的形式。Socket通讯是网络游戏最为基础的知识,因此这个实例能向有志投身于网游行业的初学者提供指导意义。
这篇文章来自狗刨学习网
Program.cs
1. using System;
2. using System.Collections.Generic;
3. using System.Linq;
4. using System.Text;
5. using System.Net.Sockets;
6.
7. namespace TestServer
8. {
9. class Program
10. {
11. // 设置连接端口
12. const int portNo = 500; 13.
14. static void Main(string[] args) 15. {
16. // 初始化服务器IP
17. System.Net.IPAddress localAdd =
System.Net.IPAddress.Parse("127.0.0.1"); 18.
19. // 创建TCP侦听器
20. TcpListener listener = new TcpListener(localAdd, portNo);
21.
22. listener.Start();
23.
24. // 显示服务器启动信息
25. Console.WriteLine("Server is starting...\n");
26.
27. // 循环接受客户端的连接请求 28. while (true)
29. {
30. ChatClient user = new
ChatClient(listener.AcceptTcpClient()); 31.
32. // 显示连接客户端的IP与端口 33. Console.WriteLine(user._clientIP + " is joined...\n");
34. }
35. }
36. }
37. }
复制代码
ChatClient.cs
1. using System;
2. using System.Collections.Generic; 3. using System.Linq;
4. using System.Text;
5. using System.Collections;
6. using System.Net.Sockets;
7.
8. namespace TestServer
9. {
10. class ChatClient
11. {
12. public static Hashtable ALLClients = new Hashtable(); // 客户列
表
13.
14. private TcpClient _client; // 客户端实体 15. public string _clientIP; // 客户端IP 16. private string _clientNick; // 客户端昵称 17.
18. private byte[] data; // 消息数据 19.
20. private bool ReceiveNick = true; 21.
22. public ChatClient(TcpClient client) 23. {
24. this._client = client;
25.
26. this._clientIP = client.Client.RemoteEndPoint.ToString();
27.
28. // 把当前客户端实例添加到客户列表当中 29. ALLClients.Add(this._clientIP, this); 30.
31. data = new byte[this._client.ReceiveBufferSize]; 32.
33. // 从服务端获取消息
34. client.GetStream().BeginRead(data, 0,
System.Convert.ToInt32(this._client.ReceiveBufferSize), ReceiveMessage,
null);
35. }
36.
37. // 从客戶端获取消息
38. public void ReceiveMessage(IAsyncResult ar)
39. {
40. int bytesRead;
41.
42. try
43. {
44. lock (this._client.GetStream()) 45. {
46. bytesRead = this._client.GetStream().EndRead(ar);
47. }
48.
49. if (bytesRead < 1)
50. {
51. ALLClients.Remove(this._clientIP); 52.
53. Broadcast(this._clientNick + " has left the chat");
54.
55. return;
56. }
57. else
58. {
59. string messageReceived =
System.Text.Encoding.ASCII.GetString(data, 0, bytesRead); 60.
61. if (ReceiveNick)
62. {
63. this._clientNick = messageReceived; 64.
65. Broadcast(this._clientNick + " has joined the
chat.");
66.
67. //this.sendMessage("hello"); 68.
69. ReceiveNick = false; 70. }
71. else
72. {
73. Broadcast(this._clientNick + ">" +
messageReceived);
74.
75. }
76. }
77.
78. lock (this._client.GetStream()) 79. {
80. this._client.GetStream().BeginRead(data, 0,
System.Convert.ToInt32(this._client.ReceiveBufferSize), ReceiveMessage,
null);
81. }
82. }
83. catch (Exception ex)
84. {
85. ALLClients.Remove(this._clientIP); 86.
87. Broadcast(this._clientNick + " has left the chat.");
88. }
89. }
90.
91. // 向客戶端发送消息
92. public void sendMessage(string message) 93. {
94. try
95. {
96. System.Net.Sockets.NetworkStream ns; 97.
98. lock (this._client.GetStream()) 99. {
100. ns = this._client.GetStream(); 101. }
102.
103. // 对信息进行编码
104. byte[] bytesToSend =
System.Text.Encoding.ASCII.GetBytes(message);
105.
106. ns.Write(bytesToSend, 0, bytesToSend.Length);
107. ns.Flush(); 108. }
109. catch (Exception ex) 110. {
111.
112. }
113. }
114.
115. // 向客户端广播消息
116. public void Broadcast(string message)
117. {
118. Console.WriteLine(message); 119.
120. foreach (DictionaryEntry c in ALLClients)
121. {
122. ((ChatClient)(c.Value)).sendMessage(message +
Environment.NewLine);
123. }
124. }
125.
126. }
127. }
复制代码
Unity3d客户端的代码ClientHandler.cs: 1. using UnityEngine;
2. using System.Collections; 3.
4. using System;
5. using System.Collections.Generic; 6. using System.ComponentModel; 7. using System.Text;
8. using System.Net.Sockets; 9.
10. public class ClientHandler : MonoBehaviour 11. {
12. const int portNo = 500;
13. private TcpClient _client;
14. byte[] data;
15.
16. // Use this for initialization 17. void Start ()
18. {
19.
20. }
21.
22. // Update is called once per frame 23. void Update ()
24. {
25.
26. }
27.
28. public string nickName = ""; 29. public string message = ""; 30. public string sendMsg = ""; 31.
32. void OnGUI()
33. {
34. nickName = GUI.TextField(new Rect(10, 10, 100, 20),
nickName);
35. message = GUI.TextArea(new Rect(10, 40, 300, 200),
message);
36. sendMsg = GUI.TextField(new Rect(10, 250, 210, 20),
sendMsg);
37.
38. if(GUI.Button(new Rect(120, 10, 80, 20), "Connect"))
39. {
40. //Debug.Log("hello"); 41.
42. this._client = new TcpClient();
43. this._client.Connect("127.0.0.1", portNo); 44.
45. data = new byte[this._client.ReceiveBufferSize]; 46.
47. //SendMessage(txtNick.Text);
48. SendMessage(nickName); 49.
50. this._client.GetStream().BeginRead(data, 0,
System.Convert.ToInt32(this._client.ReceiveBufferSize), ReceiveMessage,
null);
51. };
52.
53. if(GUI.Button(new Rect(230, 250, 80, 20), "Send")) 54. {
55. SendMessage(sendMsg); 56. sendMsg = "";
57. };
58. }
59.
60. public void SendMessage(string message) 61. {
62. try
63. {
64. NetworkStream ns = this._client.GetStream(); 65.
66. byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
67.
68. ns.Write(data, 0, data.Length);
69. ns.Flush();
70. }
71. catch (Exception ex)
72. {
73. //MessageBox.Show(ex.ToString()); 74. }
75. }
76.
77. public void ReceiveMessage(IAsyncResult ar) 78. {
79. try
80. {
81. int bytesRead;
82.
83. bytesRead = this._client.GetStream().EndRead(ar); 84.
85. if (bytesRead < 1)
86. {
87. return;
88. }
89. else
90. {
91.
92. Debug.Log(System.Text.Encoding
.ASCII.GetString(data, 0, bytesRead));
93.
94. message +=
System.Text.Encoding.ASCII.GetString(data, 0, bytesRead); 95. }
96.
97. this._client.GetStream().BeginRead(data, 0,
System.Convert.ToInt32(this._client.ReceiveBufferSize), ReceiveMessage,
null);
98.
99.
100. }
101. catch (Exception ex)
102. {
103.
104. }
105. }
106. }