Unity UDP可发送16进制数据可重新连接

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;

namespace DAMTool
{
    public class UDPManager_Server : MonoBehaviour
    {

        public static UDPManager_Server Instance;
        [Header("是否自动获取系统IP")]
        public bool AutoSystemIP =true;
        [Header("当前系统IP")]
        public string ipAddress = "192.168.1.108";
        [Header("当前系统端口号")]
        public int ConnectPort = 7401;
        [Header("是否使用外部目标IP和端口")]
        bool UseOutTargetIPAndTargetPort = true;
        [Header("目标系统IP")]
        public string TargetIpAddress = "192.168.1.108";
        [Header("目标系统端口号")]
        public int TargetConnectPort = 7401;

        [Header("接收到的信息")]
        public string recvStr = "";
        [Header("接收到的16进制字符")]
        public string recvHexStr = "";
        Socket socket;
        EndPoint clientEnd;
        IPEndPoint ipEnd;
        string sendStr;
        byte[] recvData = new byte[1024];
        byte[] sendData = new byte[1024];
        int recvLen;
        Thread connectThread;
        Thread confirmThread;
        //发送指令确认队列
        public List<string> ConfirmStrList = new List<string>();

        //初始化
        private void Awake()
        {
            Instance = this;
        }
        private void LateUpdate()
        {

        }
        void Start()
        {
            if (AutoSystemIP)
            {
                //自动获取系统IP
                ipAddress = GetIP();
                //ipAddress = IPAddress.Any.ToString();
            }
            if(UseOutTargetIPAndTargetPort)
            {
                //加载外部IP和端口完成后初始化socket
                LoadUDPData_OutIP_OutPort(InitSocket);
            }
            


            //在这里初始化server
            //ConfirmStrList.Add("1234");
        }
        /// <summary>
        /// 开启加载线程
        /// </summary>
        /// <param name="fun"></param>
        public void LoadUDPData_OutIP_OutPort(UnityAction fun=null)
        {
            StartCoroutine(ReallyLoadUDPData(fun));
            
        }
        /// <summary>
        /// 加载UDP数据
        /// </summary>
        /// <param name="fun">加载完毕执行的方法</param>
        /// <returns></returns>
        IEnumerator ReallyLoadUDPData(UnityAction fun=null)
        {
            string UDPDataFilePath = Path.Combine(Application.streamingAssetsPath, "SystemData");
            UDPDataFilePath = Path.Combine(UDPDataFilePath, "UDPData.csv");
            WWW www = new WWW(UDPDataFilePath);
            yield return www;
            if (www.isDone && !string.IsNullOrEmpty(www.text))
            {
                string[] content = www.text.Split('\n');
                content[1] = content[1].Replace("\r", "");
                TargetIpAddress= content[1].Split(',')[0];
                TargetConnectPort=int.Parse( content[1].Split(',')[1]);
                if (fun != null)
                {
                    fun();
                }
            }
            

            
        }
        /// <summary>
        /// 初始化套接字
        /// </summary>
        public void InitSocket()
        {
            //防止出现连接错误
            uint IOC_IN = 0x80000000;
            uint IOC_VENDOR = 0x18000000;
            uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
            Debug.Log(ipAddress + ":" + ConnectPort);
            ipEnd = new IPEndPoint(IPAddress.Parse(ipAddress), ConnectPort);
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            socket.Bind(ipEnd);
#if UNITY_IPHONE
            //IOS该代码会报错
#else
            
            socket.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null);
#endif
            //定义客户端
            //IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
            IPEndPoint sender = new IPEndPoint(IPAddress.Parse(TargetIpAddress), TargetConnectPort);
            clientEnd = (EndPoint)sender;
            print("等待连接数据");
            //开启一个线程连接
            connectThread = new Thread(new ThreadStart(SocketReceive));
            confirmThread = new Thread(new ThreadStart(StrConfirm));
            connectThread.Start();
            confirmThread.Start();



        }
        /// <summary>
        /// 套接字发送内容
        /// </summary>
        /// <param name="sendStr">发送内容</param>
        /// <param name="needConfirm">是否加入确认数组,默认为不加入</param>
        public void SocketSend(string sendStr,string IP="",int Port=0, bool needConfirm = false)
        {
            if(IP!=""&&Port!=0)
            {
                EndPoint clientEndNew;
                IPEndPoint sender = new IPEndPoint(IPAddress.Parse(IP), Port);
                clientEndNew = (EndPoint)sender;

                Debug.Log("发送数据给指定目标,IP:"+IP+" Port:"+Port +" 内容:"+ sendStr);
                sendData = new byte[1024];
                sendData = Encoding.UTF8.GetBytes(sendStr);
                socket.SendTo(sendData, sendData.Length, SocketFlags.None, clientEndNew);
                if (needConfirm)
                {
                    if (!ConfirmStrList.Contains(sendStr))
                    {
                        ConfirmStrList.Add(sendStr);
                    }

                }
            }
            else
            {
                Debug.Log("发送数据给指定目标,IP:" + TargetIpAddress + " Port:" + TargetConnectPort + " 内容:" + sendStr);
                sendData = new byte[1024];
                sendData = Encoding.UTF8.GetBytes(sendStr);
                socket.SendTo(sendData, sendData.Length, SocketFlags.None, clientEnd);
                if (needConfirm)
                {
                    if (!ConfirmStrList.Contains(sendStr))
                    {
                        ConfirmStrList.Add(sendStr);
                    }

                }
            }

            

        }
        /// <summary>
        /// 发送16进制指令
        /// </summary>
        /// <param name="sendStr">发送内容</param>
        public void SocketSendHex(string sendStr, string IP = "", int Port = 0, bool needConfirm = false)
        {
            if (IP != "" && Port != 0)
            {
                EndPoint clientEndNew;
                IPEndPoint sender = new IPEndPoint(IPAddress.Parse(IP), Port);
                clientEndNew = (EndPoint)sender;

                Debug.Log("发送16进制数据,IP:" + IP + " Port:" + Port + " 内容:" + sendStr);
                sendData = new byte[1024];
                sendData = DAMDataManager.Instance.HexStringSToByteArray(sendStr);
                socket.SendTo(sendData, sendData.Length, SocketFlags.None, clientEndNew);
                if (needConfirm)
                {
                    if (!ConfirmStrList.Contains(sendStr))
                    {
                        ConfirmStrList.Add(sendStr);
                    }
                }

            }
            else
            {
                Debug.Log("发送16进制数据,IP:" + TargetIpAddress + " Port:" + TargetConnectPort + " 内容:" + sendStr);
                sendData = new byte[1024];
                sendData = DAMDataManager.Instance.HexStringSToByteArray(sendStr);
                socket.SendTo(sendData, sendData.Length, SocketFlags.None, clientEnd);
                if (needConfirm)
                {
                    if (!ConfirmStrList.Contains(sendStr))
                    {
                        ConfirmStrList.Add(sendStr);
                    }
                }
            }

            
        }



        //服务器接收
        void SocketReceive()
        {
            recvData = new byte[1024];
            while (true)
            {

                recvLen = socket.ReceiveFrom(recvData, ref clientEnd);
                recvStr = Encoding.UTF8.GetString(recvData, 0, recvLen);
                recvHexStr = Byte2Hex(recvData, recvLen);
                Debug.Log("收到的信息 " + recvStr);
                Debug.Log("收到的Hex字符串" + recvHexStr+" "+clientEnd);
                //SocketSend(recvStr);


            }
        }
        //字符确认
        void StrConfirm()
        {
            while (true)
            {
                if (recvStr != "")
                {
                    //Debug.Log(ConfirmStrList.Contains(recvStr));
                    if (ConfirmStrList.Contains(recvStr))
                    {

                        ConfirmStrList.Remove(recvStr);
                        Debug.Log("收到字符串" + recvStr);
                        recvStr = "";

                    }
                }
            }
        }
        //连接关闭
        void SocketQuit()
        {
            //关闭线程
            if (connectThread != null)
            {
                connectThread.Interrupt();
                connectThread.Abort();
            }
            if (confirmThread != null)
            {
                confirmThread.Interrupt();
                confirmThread.Abort();
            }
            //最后关闭socket
            if (socket != null)
                socket.Close();
            Debug.LogWarning("断开连接");
        }
        //重新连接
        // Use this for initialization
        public void ReConnectServer()
        {

            SocketQuit();
            InitSocket();
        }

        void OnApplicationQuit()
        {
            SocketQuit();
        }
        /// <summary>
        /// 获取IP,安卓端不可用
        /// </summary>
        /// <param name="Addfam"></param>
        /// <returns></returns>
        public string GetIP(ADDRESSFAM Addfam)
        {
            //Return null if ADDRESSFAM is Ipv6 but Os does not support it
            if (Addfam == ADDRESSFAM.IPv6 && !Socket.OSSupportsIPv6)
            {
                return null;
            }

            string output = "";

            foreach (NetworkInterface item in NetworkInterface.GetAllNetworkInterfaces())
            {
#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
                NetworkInterfaceType _type1 = NetworkInterfaceType.Wireless80211;
                NetworkInterfaceType _type2 = NetworkInterfaceType.Ethernet;

                if ((item.NetworkInterfaceType == _type1 || item.NetworkInterfaceType == _type2) && item.OperationalStatus == OperationalStatus.Up)
#endif
                {
                    foreach (UnicastIPAddressInformation ip in item.GetIPProperties().UnicastAddresses)
                    {
                        //IPv4
                        if (Addfam == ADDRESSFAM.IPv4)
                        {
                            if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
                            {
                                output = ip.Address.ToString();
                                Debug.Log("" + output);
                            }
                        }

                        //IPv6
                        else if (Addfam == ADDRESSFAM.IPv6)
                        {
                            if (ip.Address.AddressFamily == AddressFamily.InterNetworkV6)
                            {
                                output = ip.Address.ToString();
                            }
                        }
                    }
                }
            }
            return output;
        }
        //或取系统IP
        public string GetIP()
        {
            string AddressIP = string.Empty;
#if UNITY_IPHONE
        NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces(); ;
        foreach (NetworkInterface adapter in adapters)
        {
            if (adapter.Supports(NetworkInterfaceComponent.IPv4))
            {
                UnicastIPAddressInformationCollection uniCast = adapter.GetIPProperties().UnicastAddresses;
                if (uniCast.Count > 0)
                {
                    foreach (UnicastIPAddressInformation uni in uniCast)
                    {
                        //得到IPv4的地址。 AddressFamily.InterNetwork指的是IPv4
                        if (uni.Address.AddressFamily == AddressFamily.InterNetwork)
                        {
                            AddressIP = uni.Address.ToString();
                        }
                    }
                }
            }
        }
            return AddressIP;
#endif



            string IP = "";
            IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName());   //Dns.GetHostName()获取本机名Dns.GetHostAddresses()根据本机名获取ip地址组
            foreach (IPAddress ip in ips)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    IP = ip.ToString();  //ipv4

                }

                else if (ip.AddressFamily == AddressFamily.InterNetworkV6)
                {
                    IP = ip.ToString(); //ipv6
                }


            }
            return IP;
        }



        //byte转16进制数
        static string Byte2Hex(byte wbyte)
        {
            string ret = null;
            var arr = "0123456789ABCDEF";
            var len = arr.Length;
            ret += arr[wbyte / len].ToString();
            ret += arr[wbyte % len].ToString();
            return ret;
        }
        //btye数组转字符,需要数组长度
        static string Byte2Hex(byte[] _byte, int _Length)
        {
            string HexStr = null;
            for (int i = 0; i < _Length; i++)
            {
                HexStr += Byte2Hex(_byte[i]);
            }

            return HexStr;
        }



    }
}
public enum ADDRESSFAM
{
    IPv4, IPv6
}



已用于很多项目,效果不错,用的话需要稍作修改

补充

public void InitSocket()
        {
            //防止出现连接错误
            //uint IOC_IN = 0x80000000;
            //uint IOC_VENDOR = 0x18000000;
            //uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
            Debug.Log(ipAddress + ":" + ConnectPort);
            ipEnd = new IPEndPoint(IPAddress.Parse(ipAddress), ConnectPort);
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            socket.Bind(ipEnd);
#if UNITY_IPHONE
            //IOS该代码会报错
#else
            
            //socket.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null);
#endif
            //定义客户端
            //IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
            IPEndPoint sender = new IPEndPoint(IPAddress.Parse(TargetIpAddress1), TargetConnectPort1);
            clientEnd = (EndPoint)sender;
            print("等待连接数据");
            //开启一个线程连接
            connectThread = new Thread(new ThreadStart(SocketReceive));
            confirmThread = new Thread(new ThreadStart(StrConfirm));
            connectThread.Start();
            confirmThread.Start();



        }

在安卓端如果出现无法收到消息,但是可以发送消息的情况,将初始化方法中的防止出现连接错误的代码注释掉就可以了

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Unity中,要发送16进制数据流,可以通过TCP连接来实现。下面是一个示例代码,解释了如何在Unity发送16进制数据。 首先,需要使用Unity内置的NetworkStream类和TcpClient类来创建TCP连接发送数据。然后,将要发送数据从字符串转换为16进制字节数组。最后,使用NetworkStream的Write方法发送字节数组。 ```c# using UnityEngine; using System; using System.IO; using System.Net; using System.Net.Sockets; public class TcpSender : MonoBehaviour { public string serverIP = "127.0.0.1"; public int serverPort = 8888; public string hexData = "ff00d245370022"; private TcpClient client; private NetworkStream stream; void Start() { client = new TcpClient(); client.Connect(IPAddress.Parse(serverIP), serverPort); stream = client.GetStream(); SendHexData(hexData); client.Close(); } private void SendHexData(string hexData) { try { byte[] byteArray = StringToByteArray(hexData); stream.Write(byteArray, 0, byteArray.Length); Debug.Log("数据发送"); } catch (Exception e) { Debug.Log("发送失败:" + e.Message); } } private byte[] StringToByteArray(string hex) { hex = hex.Replace(" ", ""); int charCount = hex.Length; byte[] byteArray = new byte[charCount / 2]; for (int i = 0; i < charCount; i += 2) byteArray[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16); return byteArray; } } ``` 在此示例中,我们创建了一个TcpSender类,该类在Start()方法中创建TCP连接,并通过SendHexData()方法发送16进制数据。StringToByteArray()方法将16进制字符串转换为字节数组,然后使用NetworkStream的Write()方法发送字节数组。需要根据实际情况修改serverIP、serverPort和hexData的值。 请注意,该代码仅提供了一个基本的示例,实际应用中可能需要更多的错误处理和异常处理机制来确保数据正确发送
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值