上面咱们建立了tcp的客户端和服务端,可是只能进行消息的一次收发。此次咱们作一个unity的简易聊天室,使用了线程,能够使用多个客户端链接服务器,而且一个客户端给服务器发消息后,服务器会将消息群发给全部客户端。服务器
服务器端分为Program和Client,在Program中进行Ip和端口的绑定并与客户端创建链接,消息的接收和发送放在Client中、socket
服务端之Program:tcp
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:spa
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界面线程
代码:code
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();//关闭链接 } }