使用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