C#程式設計 socket程式設計之unity聊天室
阿新 • • 發佈:2018-12-16
上面我們建立了tcp的客戶端和服務端,但是隻能進行訊息的一次收發。這次我們做一個unity的簡易聊天室,使用了執行緒,可以使用多個客戶端連線伺服器,並且一個客戶端給伺服器發訊息後,伺服器會將訊息群發給所有客戶端。
伺服器端分為Program和Client,在Program中進行Ip和埠的繫結並與客戶端建立連線,訊息的接收和傳送放在Client中、
服務端之Program:
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Net.WebSockets; using System.Text; using System.Threading.Tasks; namespace _022_聊天室_socket_tcp伺服器端 { class Program { static List<Client> clientList = new List<Client>(); // 廣播訊息 public static void BroadcastMessage(string message) { var notConnectedList = new List<Client>(); foreach (var client in clientList) { if (client.Connected) client.SendMessage(message); else { notConnectedList.Add(client); } } foreach (var temp in notConnectedList) { clientList.Remove(temp); } } static void Main(string[] args) { Socket tcpServer = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp); tcpServer.Bind(new IPEndPoint(IPAddress.Parse("192.168.1.101"),7788)); tcpServer.Listen(100); Console.WriteLine("server running..."); while (true) { Socket clientSocket = tcpServer.Accept(); Console.WriteLine("a client is connected !"); Client client = new Client(clientSocket);//把與每個客戶端通訊的邏輯(收發訊息)放到client類裡面進行處理 clientList.Add(client); } } } }
服務端之Client:
using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; namespace _022_聊天室_socket_tcp伺服器端 { // 用來跟客戶端做通訊 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); //接收到資料的時候 要把這個資料 分發到客戶端 //廣播這個訊息 Program.BroadcastMessage(message); Console.WriteLine("收到了訊息:"+message); } } // 傳送訊息 public void SendMessage(string message) { byte[] data = Encoding.UTF8.GetBytes(message); clientSocket.Send(data); } // 判斷是否連線 public bool Connected { get { return clientSocket.Connected; } } } }
客戶端:因為是基於unity的聊天室,所以首先建立簡單的UI介面
程式碼:
using UnityEngine; using System.Collections; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; public class ChatManager : MonoBehaviour { public string ipaddress = "192.168.1.101"; public int port = 7788; public UIInput textInput; public UILabel chatLabel; private Socket clientSocket; private Thread t; private byte[] data = new byte[1024];//資料容器 private string message = "";//訊息容器 void Start () { ConnectToServer(); } void Update () { if (message != null && message != "") { chatLabel.text += "\n" + message; message = "";//清空訊息 } } void ConnectToServer() { clientSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp); //跟伺服器端建立連線 clientSocket.Connect( new IPEndPoint(IPAddress.Parse(ipaddress),port) ); //建立一個新的執行緒 用來接收訊息 t = new Thread(ReceiveMessage); t.Start(); } // 這個執行緒方法 用來迴圈接收訊息 void ReceiveMessage() { while (true) { if (clientSocket.Connected == false) break; int length = clientSocket.Receive(data); message = Encoding.UTF8.GetString(data, 0, length); //chatLabel.text += "\n" + message; } } // 傳送訊息 void SendMessage(string message) { byte[] data = Encoding.UTF8.GetBytes(message); clientSocket.Send(data); } // 傳送按鈕點選 public void OnSendButtonClick() { string value = textInput.value; SendMessage(value); textInput.value = ""; } void OnDestroy() { clientSocket.Shutdown(SocketShutdown.Both); clientSocket.Close();//關閉連線 } }