unityc#中使用udp进行数据发送和接收数据

发送数据
UdpServer:

using UnityEngine;
using System.Collections;
//引入库
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.IO;
using System;

public class UdpServer : MonoBehaviour
{
    //以下默认都是私有的成员
    Socket socket; //目标socket
    EndPoint clientEnd; //客户端
    IPEndPoint ipEnd; //侦听端口
    string sendStr; //发送的字符串
    byte[] sendData = new byte[1024]; //发送的数据,必须为字节
    Thread connectThread; //连接线程
    Emulation emul;
    StreamReader streamReader;

    //初始化
    void InitSocket()
    {
        //定义服务端
        IPAddress IPadd = IPAddress.Parse("127.0.0.1");
        ipEnd = new IPEndPoint(IPadd, 8002);
        //定义套接字类型,在主线程中定义
        socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        //服务端需要绑定ip
        socket.Bind(ipEnd);
        //定义客户端
        IPEndPoint sender = new IPEndPoint(IPadd, 8001);
        clientEnd = (EndPoint)sender;
        print("waiting for UDP dgram");
    }
    //连接关闭
    void SocketQuit()
    {
        //关闭线程
        if (connectThread != null)
        {
            connectThread.Interrupt();
            connectThread.Abort();
        }
        //最后关闭socket
        if (socket != null)
            socket.Close();
        print("disconnect");
    }
    // Use this for initialization
    void Start()
    {
        streamReader = new StreamReader(Application.dataPath + "/theDegreesdata.txt");
        InitSocket(); //在这里初始化server
    }

    // Update is called once per frame
    void Update()
    {
        string strLine = streamReader.ReadLine();
        //print("strLine:" + strLine);
        if (strLine != null)
        {
            string[] sts = strLine.Split(',');
            if (sts.Length == 2)
            {
                string strX = sts[0];
                string strY = sts[1];
                float theX = System.Convert.ToSingle(strX);
                float theY = System.Convert.ToSingle(strY);
                byte[] a = BitConverter.GetBytes(theX);
                byte[] b = BitConverter.GetBytes(theY);
                byte[] c = new byte[a.Length + b.Length];
                a.CopyTo(c, 0);
                b.CopyTo(c, 4);
                socket.SendTo(c, c.Length, SocketFlags.None, clientEnd);
            }
        }
    }

    void OnApplicationQuit()
    {
        streamReader.Close();
        SocketQuit();
    }
}

发送的数据为从txt文件中按行读取的经纬度信息,转为byte发送。

客户端
UDPmanager

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;
public class UDPmanager : MonoBehaviour {

    public float lon = 0;
    public float lat = 0;
    public float preLon = 0;
    public float preLat = 0;
    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;
        }
    }
    string receiveData = string.Empty;
    private Action<string> ReceiveCallBack = null;
    private Thread RecviveThread;
    private void Start()
    {
        //print("开启线程");
        //开启线程
        ThreadRecvive();
    }
    private void Update()
    {
        if (ReceiveCallBack != null && !string.IsNullOrEmpty(receiveData))
        {
            //调用处理函数对数据进行处理,RecieveCallBack参数是一个方法,所以可以对recieveData数据进行处理
            //但是这个参数方法需要自己写,在NetController里面自定义
            ReceiveCallBack(receiveData);
            //使用之后清空接受的数据
            receiveData = string.Empty;
        }
    }
    private void OnDestroy()
    {
        if (RecviveThread != null)
        {
            RecviveThread.Abort();
        }
    }
    //Action<string> action==RecieveCallBack参数是一个方法
    public void SetReceiveCallBack(Action<string> action)
    {
        ReceiveCallBack = action;
    }
    /// <summary>
    /// 开始线程接收
    /// </summary>
    private void ThreadRecvive()
    {
        print("开启线程");
        //开一个新线程接收UDP发送的数据
        RecviveThread = new Thread(() =>
        {
            //实例化一个IPEndPoint,任意IP和对应端口 端口自行修改
            IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8001);//数据从哪传来的的地址和端口号
            UdpClient udpReceive = new UdpClient(endPoint);
            //实例化一个UdpData对象
            UDPData data = new UDPData(endPoint, udpReceive);//udp数据
            //开启异步接收data里面的数据
            udpReceive.BeginReceive(CallBackRecvive, data);//接收数据
        })
        {
            //设置为后台线程
            IsBackground = true
        };
        
        //开启线程
        RecviveThread.Start();
        print("开启了!!!");
    }

    /// <summary>
    /// 异步接收回调
    /// </summary>
    /// <param name="ar"></param>
    private void CallBackRecvive(IAsyncResult ar)
    {
        print("接收数据");
        try
        {
            //将传过来的异步结果转为我们需要解析的类型
            //获取udpdata里面的UDPClient参数和IPEndPoint参数
            UDPData state = ar.AsyncState as UDPData;
            IPEndPoint ipEndPoint = state.EndPoint;
            //结束异步接受 不结束会导致重复挂起线程卡死
            byte[] data = state.UDPClient.EndReceive(ar, ref ipEndPoint);
            print("data.length::" + data.Length);
            byte[] byte_lon = { data[0], data[1], data[2], data[3] };
            byte[] byte_lat = { data[4], data[5], data[6], data[7] };

            lon = BitConverter.ToSingle(byte_lon, 0);
            lat = BitConverter.ToSingle(byte_lat, 0);
            //解析数据(字节流),去掉源端口目的端口和长度等,只留下数据 编码自己调整暂定为默认 依客户端传过来的编码而定
            //  string receiveData = Encoding.Default.GetString(data);
            //  Debug.Log(receiveData);
            //数据的解析再Update里执行 Unity中Thread无法调用主线程的方法
            //再次开启异步接收数据
            state.UDPClient.BeginReceive(CallBackRecvive, state);
        }
        catch (Exception e)
        {
            Debug.LogError(e.Message);
            throw;
        }
    }
    /// <summary>
    /// 发送UDP信息
    /// </summary>
    /// <param name="remoteIP">发送地址</param>
    /// <param name="remotePort">发送端口</param>
    /// <param name="message">需要发送的信息</param>
    public void UDPSendMessage(string remoteIP, int remotePort, string message)
    {
        //将需要发送的内容转为byte数组 编码以接收端为主,自行修改
        byte[] sendbytes = Encoding.Unicode.GetBytes(message);
        IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Parse(remoteIP), remotePort);
        UdpClient udpSend = new UdpClient();
        //发送数据到对应目标
        udpSend.Send(sendbytes, sendbytes.Length, remoteIPEndPoint);
        //关闭
        udpSend.Close();
    }
}

收到的数据解析回经纬度信息。

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值