Comunicación UDP y TCP en unidad para obtener la IP del cliente

Este artículo usa udpclient y tcpclient en lugar de instancias de socket

Espacios de nombres

using System.Net;
using System.Net.Sockets;

Los objetos centrales de TCP
TCP son TcpListener y TcpClient. El primero se usa para que el servidor monitoree las solicitudes de conexión y cree un objeto TcpClient. Cuando se requiera comunicación, use directamente el TcpClient creado para llamar a los métodos Enviar y Recibir.

Escuchar conexiones: TCP debe estar conectado, por lo que se necesita un escucha de conexión. El servidor escucha las conexiones de los clientes de la siguiente manera

    /// <summary>
    /// TCP连接请求监听者
    /// </summary>
    private TcpListener tcpListener;
   
    private void Awake()
    {
    
           
        //开启连接监听的线程,必须另开一个线程启动监听,如果在主线程里直接调用,主线程会阻塞
        tcpListenerT = new Thread(ListenConnect);
        tcpListenerT.IsBackground = true;
        tcpListenerT.Start();
    }

   //监听连接请求的方法
    private void ListenConnect()
    {
    
    
        //声明监听者的IP为任意可用`在这里插入代码片`
        tcpListener = new TcpListener(new IPEndPoint(IPAddress.Any, 10086));
        tcpListener.Start(100);//监听请求 最多连接100个
        while (true)
        {
    
    
            //这一步会阻塞线程,不能在主线程中调用
            TcpClient client = tcpListener.AcceptTcpClient();  
            //获取客户端的IP          
            string ip = (client.Client.RemoteEndPoint as IPEndPoint).Address.ToString();                      
        }
    }

El cliente se conecta al servidor:

 private TcpClient tcpClient = new TcpClient();
 private void Start()
 {
    
    
     //参数为服务器的地址,和服务器的TcpListener绑定的端口
     tcpClient.Connect("192.168.1.36", 10086);
 }

enviar mensajes:

    public void SendMsg(TcpClient client,string msg)
    {
    
    
         byte[] buff = Encoding.UTF8.GetBytes(msg);
         client.Send(buff);
    }

Recibir mensaje:

    private TcpClient tcpClient = new TcpClient();

    private void Start()
    {
    
    
        //连接到服务器
        tcpClient.Connect("192.168.1.36", 10086);
        //接收消息的方法必须在子线程中执行
        tcpReciveT = new Thread(Recciveimage);
        tcpReciveT.IsBackground = true;
        tcpReciveT.Start();
    }

    /// <summary>
    /// 接收字节数组
    /// </summary>
    private void Recciveimage()
    {
    
    
        //声明接收缓冲区的长度
        byte[] receiveBuff = new byte[1024];
        int reviceLength = 0;
        while (true)
        {
    
    
            try
            {
    
    
                //返回值为接收到的字节的数量 这一步会阻塞线程,决不能在主线程中执行
                reviceLength = tcpClient.Client.Receive(receiveBuff);
                //必须指定转换的字节数组的长度,因为缓冲区剩余的空位会用0填充,这些0我们并不需要
                msg = Encoding.UTF8.GetString(receiveBuff,0,reviceLength);
                isReveive = true;
                print("收到的消息 "+msg);
            }
        }
    }

UDP
UDP es relativamente simple, UDP no requiere conexión, los objetos centrales son UdpClinent e IPEndPoint

UdpClient es el objeto de UDP, utilizado para enviar y recibir mensajes

IPEndPoint puede entenderse como el punto final de la comunicación Udp, resolviendo tres problemas ¿Quién soy? ¿Dónde lo voy a enviar? ¿De dónde recibo?
Al declarar UdpClient, debe especificar el IPEndPoint de UdpClient, es decir, ¿quién soy?
Al enviar un mensaje a través de UdpClient, debe especificar el IPEndPoint del destino, es decir, donde quiero enviar un
mensaje para recibir un mensaje a través de UdpClient, debe especificar el IPEndPoint de escucha, es decir, de dónde lo obtengo

Hay dos construcciones comúnmente utilizadas de IPEndPoint, las cuales requieren que especifiquemos la IP y el puerto, y usemos la clase IPAddress para especificar la IP en el constructor.

//IP为当前可用IP,或任意IP  端口为0表示任何端口, 这种声明通常在接收消息中使用
new IPEndPoint(IPAddress.Any, 0)
//指定一个IP,255.255.255.255为群发  端口为40000  指定确定的IP端口通常用于声明UdpClient和发送消息
new IPEndPoint(IPAddress.Parse("192.168.1.36"), 40000)

enviar

    //公共的消息发送中心
    private UdpClient udpClient;
    private  void Awake()
    {
    
            
        //为UdpClient绑定本机的IP和端口  我是谁
        udpClient = new UdpClient(new IPEndPoint(IPAddress.Any, 40000));
    }
    
    /// <summary>
    /// 消息发送  IPEndPoint声明 IPEndPoint = new IPEndPoint(IPAddress.Parse("192.168.1.36"),10000)
    /// </summary>
    public void CommonendMsgSender(string msg, IPEndPoint commonIPEndPoint)
    {
    
    
        byte[] commonBuff = Encoding.UTF8.GetBytes(msg);
        udpClient.Send(commonBuff, commonBuff.Length, commonIPEndPoint);
    }

monitor

    private UdpClient CommonUdpClient;
    // 公共的消息接收端口
    private IPEndPoint commonReceiveIPEndPoint;
    // 公共的消息线程
    Thread commonReceiveThread;
    // 公共消息的缓存
    private byte[] commonMsgBuff;

    private void Start()
    {
    
    
        //公共消息接收端口
        commonReceiveIPEndPoint = new IPEndPoint(IPAddress.Any, 0);
        //启动监听线程,和TCP一样,监听会阻塞线程,不能在主线程中监听消息
        commonReceiveThread = new Thread(ListenCommonMsg);
        commonReceiveThread.IsBackground = true;
        commonReceiveThread.Start();
    }
    // 监听公共消息
    private void ListenCommonMsg()
    {
    
    
        while (true)
        {
    
    
            //这里会阻塞线程
            commonMsgBuff = CommonUdpClient.Receive(ref commonReceiveIPEndPoint);
            string temp = Encoding.UTF8.GetString(commonMsgBuff);
            print("公共消息为" + temp);
        }
    }
    

Notas
1. La operación de escucha debe realizarse en el subproceso, no en el subproceso principal, de lo contrario, el subproceso principal se bloqueará.
2. La escucha repetida de mensajes debe usar un bucle infinito
. 3. El subproceso puede operar el propiedades simples del hilo principal. No puede manipular directamente objetos Uinty como Texto, etc. Si necesita cambiar el contenido de la escena después de recibir un mensaje, use un bool para hacer un bloqueo en Actualizar en un script del hilo principal, y asigne el mensaje recibido por el subproceso secundario al subproceso principal. Variable de cadena del script y establezca el bloqueo en verdadero, use este script para controlar el objeto Uinty
Ejemplo

   //子线程接到消息后,置为true
    public bool isReceive = false;
    /// <summary>
    /// 子线程接到消息后,将消息赋值到这个变量
    /// </summary>
    public string msg;

void Update()
    {
    
    
        if (isReceive)
        {
    
    
            //处理msg
            if(msg == "1")
            {
    
    
                //逻辑
            }
        }
    }

Supongo que te gusta

Origin blog.csdn.net/weixin_44568736/article/details/122828374
Recomendado
Clasificación