找回密码
 注册帐号

扫一扫,访问微社区

Like Unity网络编程之UDPClent实现局域网通信

0
回复
430
查看
[ 复制链接 ]
排名
64950
昨日变化

4

主题

19

帖子

221

积分

Rank: 9Rank: 9Rank: 9

UID
354297
好友
0
蛮牛币
485
威望
0
注册时间
2020-11-3
在线时间
196 小时
最后登录
2020-11-27
2020-11-6 13:59:13 显示全部楼层 阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
【前言】

UDP通信,是我最开始做一个视频同步的功能开始学习的,随后就开始使用UDPClent做网络传输,我的理解中,UDPClent是system.net网络程序集下的一个关于UDP的网络管理器,底层也是和TCP一样的Socket相关功能封装,多得也不说了,下面我直接放出代码,实现一个简单的发送、接收案例。


【基于UDPClent封装的网络管理器类——UDP_Manager】


接收是同一端口全部接收,所以收发注意一下端口号,收发的端口号要一致。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;
public class UDP_Manager : MonoBehaviour
{
    public class UDPData
    {
        private readonly UdpClient udpClient;
        public UdpClient UDPClient
        {
            get { return udpClient; }
        }
        private readonly IPEndPoint endPoint;
        public IPEndPoint EndPoint
        {
            get { return endPoint; }
        }
        //构造函数
        public UDPData(IPEndPoint endPoint UdpClient udpClient)
        {
            this.endPoint = endPoint;
            this.udpClient = udpClient;
        }
    }
    public static UDP_Manager m_instance;
    string receiveData = string.Empty;
    private Action<string> ReceiveCallBack = null;
    private Thread RecviveThread;
    public UdpClient udpReceive;
    private void Awake()
    {
        if (m_instance == null)
        {
            m_instance = this;
        }
        else
        {
            Destroy(this);
        }
    }
    private void Update()
    {
        if (ReceiveCallBack != null &&
            !string.IsNullOrEmpty(receiveData))
        {
            //print(\\\\\\\"udp管理打开线程\\\\\\\");
            //调用处理函数去数据进行处理
            ReceiveCallBack(receiveData);
            //使用之后清空接受的数据
            receiveData = string.Empty;
        }
    }
    public void SetReceiveCallBack(Action<string> action)
    {
        //print(\\\\\\\"设置接收回调\\\\\\\");
        ReceiveCallBack = action;
        ThreadRecvive();
    }
    /// <summary>
    /// 开始线程接收
    /// </summary>
    public void ThreadRecvive()
    {
        try
        {
            //开一个新线程接收UDP发送的数据
            RecviveThread = new Thread(() =>
            {
                print(\\\\\\\"开启线程\\\\\\\");
                //实例化一个IPEndPoint,任意IP和对应端口 端口自行修改
                IPEndPoint endPoint = null;
                endPoint = new IPEndPoint(IPAddress.Any 9527);
                print(endPoint);
                udpReceive = new UdpClient(endPoint);
                UDPData data = new UDPData(endPoint udpReceive);
                //开启异步接收
                udpReceive.BeginReceive(CallBackRecvive data);
            })
            {
                //设置为后台线程
                IsBackground = true
            };
            //开启线程
            RecviveThread.Start();
        }
        catch (Exception ex)
        {
            print(\\\\\\\"开启线程异常:\\\\\\\" + ex);
        }
    }
    /// <summary>
    /// 异步接收回调
    /// </summary>
    /// <param name=\\\\\\\"ar\\\\\\\"></param>
    private void CallBackRecvive(IAsyncResult ar)
    {
        UDPData state = null;
        try
        {
            //将传过来的异步结果转为我们需要解析的类型
            state = ar.AsyncState as UDPData;
            IPEndPoint ipEndPoint = state.EndPoint;//print(ipEndPoint.Address.ToString());
            //print(ipEndPoint.Port);
            //结束异步接受 不结束会导致重复挂起线程卡死
            byte[] data = new byte[1024];
            data = state.UDPClient.EndReceive(ar ref ipEndPoint);
            //receiveData = Encoding.GetEncoding(\\\\\\\"GB2312\\\\\\\").GetString(data);
            receiveData = Encoding.Default.GetString(data);
            //Debug.Log(receiveData);
            //数据的解析再Update里执行 Unity中Thread无法调用主线程的方法
            //再次开启异步接收数据
            state.UDPClient.BeginReceive(CallBackRecvive state);
        }
        catch (Exception e)
        {
            state.UDPClient.Close();
            print(\\\\\\\"接收异常关闭接收:\\\\\\\" + e);
        }
    }
    UdpClient udpSend;
    public void UDPSendMessage(string message string ip int port)
    {
        //将需要发送的内容转为byte数组 编码依接收端为主,自行修改
        byte[] sendbytes = Encoding.Default.GetBytes(message);
        IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Parse(ip) port);
        udpSend = new UdpClient();
        //发送数据到对应目标
        udpSend.Send(sendbytes sendbytes.Length remoteIPEndPoint);
        //关闭
        udpSend.Close();
    }
    private void OnApplicationQuit()
    {
        if (RecviveThread != null)
        {
            RecviveThread.Abort();
        }
        if (udpReceive != null)
        {
            udpReceive.Close();
            print(\\\\\\\"UDP接收关闭\\\\\\\");
        }
        //关闭
        if (udpSend != null)
            udpSend.Close();
        //print(\\\\\\\"UDP管理器关闭\\\\\\\");
    }
}


【测试发送功能——UDP_Send】


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UDP_Send : MonoBehaviour
{
    private void Update()
    {
        if (Input.GetMouseButtonDown(1))
        {
            UDP_Manager.m_instance.UDPSendMessage(\\\\\\\"我是你爹我爱你\\\\\\\"\\\\\\\"127.0.0.1\\\\\\\"9527);//可以根据IP地址自行更改
            print(\\\\\\\"点击发送了==我是你爹我爱你\\\\\\\" );
        }
    }
}


【测试接收功能——UDP_Receive】


using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UDP_Receive : MonoBehaviour
{
    // Start is called before the first  update
    void Start()
    {
        UDP_Manager.m_instance.SetReceiveCallBack(ReceiveCallBack);
    }
    private void ReceiveCallBack(string message)
    {
        print(\"接收到消息=\"+message);
    }
}












回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则