使用Tcp協議實現最簡單的本地局域網聊天
一、思路
服務器html
- 先用C#網絡編程學習(1)---Socket之Tcp協議的簡單使用中方法寫可接收多個客戶端的鏈接代碼。
- 另外寫一個類Client專門處理鏈接的客戶端clientSocket。
- 在主類中用List<Client>存放全部鏈接的客戶端。。
- 在Client中給出接收信息(線程),發送信息,是否處於鏈接狀態方法。
- 在主類中寫廣播方法(向全部客戶端發送信息)
Unity客戶端UI 編程
Unity客戶端代碼c#
- Unity空物體ChatManager中綁定腳本ChatManager
- 遊戲開始時鏈接服務器
- 點擊按鈕事件觸發Send()發送數據方法
- 接收廣播消息的方法(線程).
二、服務器端
/// <summary> /// 主類中寫服務器信息 /// </summary> class Program { //建立一個集合記錄全部鏈接的客戶端,當廣播消息時,向鏈接的全體客戶端發送消息 private static List<Client> clientList = new List<Client>(); static void Main(string[] args) { Socket tcpServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); tcpServer.Bind(new IPEndPoint(IPAddress.Parse("192.168.1.2"), 7788)); tcpServer.Listen(100); Console.WriteLine("server running"); while (true) //用while接收多個客戶端鏈接 { Socket tcpClient = tcpServer.Accept(); Console.WriteLine("a client is connected"); //由於不只須要while接收多個客戶端,每一個客戶端也能夠一直髮送消息。因此單獨寫個類來控制客戶端比較直觀方便。 Client client = new Client(tcpClient); clientList.Add(client); } } //廣播消息 (就是向全部客戶端發送消息) public static void BroadcastMessage(string message) { List<Client> notConnectedList = new List<Client>(); //得到全部斷開鏈接的客戶端 //遍歷list集合,向全部客戶端發送消息 foreach (var client in clientList) { if (client.Connected) client.SendMessage(message); else { notConnectedList.Add(client); } } //把全部斷開鏈接的客戶端移除 foreach (var temp in notConnectedList) { clientList.Remove(temp); } } } /// <summary> /// Client類用來和客戶端作通訊 /// </summary> class Client { private Socket clientSocket; private Thread t; private byte[] data = new byte[1024]; //這個是一個數據容器 public Client(Socket s) { clientSocket = s; //啓動一個線程 處理客戶端的接收 t = new Thread(ReceiveMessage); t.Start(); } //接收客戶端的消息 private void ReceiveMessage() { //循環一直接收客戶端的數據 while (true) { //在接收數據以前,判斷socket鏈接是否斷開 if (clientSocket.Poll(10, SelectMode.SelectRead)) { clientSocket.Close(); break; //跳出循環,停止線程的執行 } int length = clientSocket.Receive(data); string message = Encoding.UTF8.GetString(data, 0, length); //消息的廣播,要放在Main裏面寫,由於在Main中存着全部鏈接的客戶端 Program.BroadcastMessage(message); Console.WriteLine("收到了消息" + message); } } //向全部客戶端發送消息 public void SendMessage(string message) { byte[] data = Encoding.UTF8.GetBytes(message); clientSocket.Send(data); } //判斷客戶端服務器是否還鏈接,不鏈接將在Main裏面刪去 public bool Connected { get { return clientSocket.Connected; } } }
三、客戶端
public class ChatManager : MonoBehaviour { private string ipAddress = "192.168.1.2"; private int port = 7788; private Socket clientSocket; public InputField textInput; //用戶輸入框 //接收服務器數據 private Thread t; private byte[] data = new byte[1024]; private string receiveMessages = ""; public Text chatText; //用戶聊天框 private void Start() { ConnectedToServer(); } private void Update() { //時刻檢測當接收到數據時,receiveMessages不爲空,數據加入到聊天框當中 if (receiveMessages != null && receiveMessages != "") { chatText.text += "\n" + receiveMessages; receiveMessages = ""; } } //程序開始時鏈接服務器 private void ConnectedToServer() { clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //發起鏈接 clientSocket.Connect(new IPEndPoint(IPAddress.Parse(ipAddress), port)); //建立一個新的線程用於接收廣播消息,由於消息要一直接收的 t = new Thread(ReceiveMessage); t.Start(); } //發送數據 private void SendMessage(string message) { byte[] data = Encoding.UTF8.GetBytes(message); clientSocket.Send(data); } //點擊按鈕觸發 public void OnSendButtonClick() { string value = textInput.text; SendMessage(value); textInput.text = ""; } //這個線程方法用於循環接收廣播消息 private void ReceiveMessage() { while (true) { //與服務器斷開鏈接時,取消線程 if (clientSocket.Connected == false) { break; } int length = clientSocket.Receive(data); receiveMessages = Encoding.UTF8.GetString(data, 0, length); //由於Unity中線程不容許直接操控UI組件,因此間接改變 } } }
四、效果
先打開VS中服務器 圖1:爲客戶端鏈接時,服務器彈出鏈接信息,服務器能夠收到客戶端發送的消息 服務器
<br> **圖2**:爲打開兩個客戶端時,一方發送消息,另外一方就能夠收到 網絡
五、百度雲源碼連接
連接:https://pan.baidu.com/s/1dsZNw8UQJ8BjJHejBzaOLg 提取碼:3ufksocket