TCP通信基于Unity3D的聊天室UDP通信

    技术2022-07-10  119

    TCP

    (1).建立一个套接字(Socket) (2).绑定服务器端IP地址及端口号–服务器端 (3).利用Listen()方法开启监听–服务器端 (4).利用Accept()方法尝试与客户端建立一个连接–服务器端 (5).利用Connect()方法与服务器建立连接–客户端 (6).利用Send()方法向建立连接的主机发送消息 (7).利用Recive()方法接受来自建立连接的主机的消息(可靠连接) 服务器端绑定IP:端口号后,局域网内的计算机都可以与这个IP进行通信,都可以跟这个计算机做通信 客户端发起建立连接的请求,客户端的IP:端口号要与服务器端绑定的IP:端口号一致才能连接 客户端

    using System.Text; using System.Net.Sockets; using System.Net; using UnityEngine; using UnityEngine.UI; using System.Threading; public class _GameManager : MonoBehaviour { public string ipAdress = "10.10.6.59";//需要连接的服务器的地址 public int port = 7788;//需要连接的服务器设置的端口 public InputField textInput; public Text textShow; private Socket clientSocket; private Thread t; private byte[] data = new byte[1204];//数据容器 private string message="";//消息容器,存储广播过来的消息 void Start() { ConnectServer(); } // Update is called once per frame void Update() { if (message !=null&&message !="") { textShow.text +="\n" +message;//显示消息 message = "";//清空消息 } } void ConnectServer() { clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //跟服务器端建立连接,服务器端绑定的IP地址就是需要连接的,客户端的ipAdress不一致就连接不上 clientSocket.Connect(new IPEndPoint(IPAddress .Parse (ipAdress), port));//通过IP+端口号定位一个要连接的服务器端 //创建一个新的线程 用来接收收消息 t = new Thread(ReceiveMessage); t.Start(); } private void ReceiveMessage() { while (true) { if (clientSocket.Poll(10, SelectMode.SelectRead)) { //clientSocket.Close(); //Debug.Log("连接已断开,客户端不再接收消息"); break; } int length = clientSocket.Receive(data);//存储字节数据于data中,并返回长度 message = Encoding.UTF8.GetString(data, 0, length); } } void _SendMessage(string message) { byte[] data = Encoding.UTF8.GetBytes(message); clientSocket.Send(data);//发送消息 } public void OnSendButtonClick() { string messageText = textInput.text;//获取输入区输入的消息 _SendMessage(messageText);//发送消息 textInput.text = "";//发送消息后,清空输入区的消息 } private void OnDestroy()//Unity按下停止按钮后,关闭程序前执行OnDestroy()函数 { //clientSocket.Shutdown(SocketShutdown.Both); //Debug.Log("连接已断开,客户端不再接收消息"); t.Abort();//关闭线程,若不关闭,结束时会输出一个错误:一个封锁操作被对 WSACancelBlockingCall 的调用中断。 clientSocket.Close();//关闭连接 } }

    服务器端Client类

    using System; using System.Text; using System.Net.Sockets; using System.Threading; namespace TCP服务器端 { class Client { private Socket clientSocket; private Thread t; private byte[] data=new byte[1024];//数据容器 public Client (Socket s)//用来做通信,在Program类里传入:Client client = new Client(clientSocket); { clientSocket = s; //启动一个线程 处理客户端的数据接收 t = new Thread(ReceiveMessage); t.Start(); } private void ReceiveMessage() { while (true)//一直接受客户端的信息 { if (clientSocket .Poll (10,SelectMode.SelectRead))//如果连接已断开,跳出循环 { clientSocket.Close(); //Console.WriteLine("连接已断开,服务器不再接收消息"); break; } int length=clientSocket.Receive(data);//接收字符数组,获取长度 string message = Encoding.UTF8.GetString(data, 0, length);//把字节数组转化为字符串 Console.WriteLine(message);//客户端控制台显示消息 //广播消息 Program.BroadcastMessage(message); //向所有连接的客户端广播消息 } } public void _SendMessage(string message) { byte[] data = Encoding.UTF8.GetBytes(message);//对字符串编码,把字符串转化为字节数组 clientSocket.Send(data);//向客户端发送 } public bool _Connected { get { return clientSocket.Connected; }//客户端是否连接 } } }

    服务器端

    using System; using System.Collections.Generic; using System.Net.Sockets; using System.Net; namespace TCP服务器端 { class Program { static List<Client> clientList = new List<Client>(); /// <summary> /// 广播消息,向多个客户端发送消息 /// </summary> /// <param name="message"></param> 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) { //1.创建Socket Socket tcpSever = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //2.绑定IP与端口号 10.10.6.59 tcpSever.Bind(new IPEndPoint(IPAddress.Parse("10.10.6.59"),7788));//IPEndPoint是对IP+端口号做了一层封装的类 //3.开始监听,等待客户端做连接 tcpSever.Listen(0);//参数是最大连接数 Console.WriteLine("开始监听"); Console.WriteLine("Sever Running"); while (true) { //使用返回的Socket做通信 Socket clientSocket = tcpSever.Accept();//暂停当前线程,直到有一个客户端连接过来,之后进行下面的代码 Console.WriteLine("一个客户端已连接"); Client client = new Client(clientSocket);//把与每个客户端做通信(收发消息)的逻辑放到Client类里处理 clientList.Add(client);//添加客户端 } } } }

    添加一个Image与一个Text,Image作为Text的背景。 添加一个InputField作为输入框。 添加一个按钮。记得注册点击事件。 添加一个空物体命名为_GameManager,挂载客户端脚本。

    UDP

    不需要连接过程,直接根据 IP:端口 收发数据

    1.只能收发一次

    using System; using System.Text; using System.Net; using System.Net.Sockets; namespace UDP客户端 { class Program { static void Main(string[] args) { //创建socket Socket udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); //发送数据 EndPoint serverPoint = new IPEndPoint(IPAddress.Parse("10.10.6.59"), 7788); string message = Console.ReadLine(); byte[] data = Encoding.UTF8.GetBytes(message); udpClient.SendTo(data, serverPoint); Console.ReadKey(); } } } using System; using System.Net; using System.Net.Sockets; using System.Text; namespace UDP服务器 { class Program { static void Main(string[] args) { //1.创建socket Socket udpServer = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); //2.绑定IP跟端口号 udpServer.Bind(new IPEndPoint(IPAddress.Parse("10.10.6.59"), 7788)); //3.接收数据 EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);//IP指定为Any,端口指定为0,后面ReceiveFrom方法会修改 byte[] data = new byte[1024]; int length=udpServer.ReceiveFrom(data, ref remoteEndPoint);//这个方法会把客户端的IP与端口号放到第二个参数,ref表示ReceiveFrom方法可以修改remoteEndPoint的属性 string message = Encoding.UTF8.GetString(data, 0, length); Console.WriteLine("从IP:" + (remoteEndPoint as IPEndPoint).Address + ":" + (remoteEndPoint as IPEndPoint).Port + "收到了数据:" + message); udpServer.Close(); Console.ReadKey(); } } }
    2.多次循环收发

    using System; using System.Text; using System.Net; using System.Net.Sockets; namespace UDP客户端 { class Program { static void Main(string[] args) { //创建socket Socket udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); while (true) { EndPoint serverPoint = new IPEndPoint(IPAddress.Parse("10.10.6.59"), 7788); string message = Console.ReadLine(); byte[] data = Encoding.UTF8.GetBytes(message); udpClient.SendTo(data, serverPoint); } } } } using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; namespace UDP服务器 { class Program { static Socket udpServer; static void Main(string[] args) { //1.创建socket udpServer = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); //2.绑定IP跟端口号 udpServer.Bind(new IPEndPoint(IPAddress.Parse("10.10.6.59"), 7788)); //3.接收数据 new Thread(ReceiveMessage) { IsBackground = true }.Start(); //udpServer.Close(); Console.ReadKey(); } static void ReceiveMessage() { while (true) { EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);//IP指定为Any,端口指定为0,后面ReceiveFrom方法会修改 byte[] data = new byte[1024]; int length = udpServer.ReceiveFrom(data, ref remoteEndPoint);//这个方法会把客户端的IP与端口号放到第二个参数,ref表示ReceiveFrom方法可以修改remoteEndPoint的属性 //会暂停等待接收数据,只有接收到了数据才会执行下面的代码 string message = Encoding.UTF8.GetString(data, 0, length); Console.WriteLine("从IP:" + (remoteEndPoint as IPEndPoint).Address + ":" + (remoteEndPoint as IPEndPoint).Port + "收到了数据:" + message); } } } }
    Processed: 0.028, SQL: 9