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

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);
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值