找回密碼
 注冊帳號

掃一掃,訪問微社區

Like Unity網絡編程之UDPClent實現局域網通信

0
回復
351
查看
打印 上一主題 下一主題
[ 復制鏈接 ]
排名
64950
昨日變化

4

主題

19

帖子

192

積分

Rank: 9Rank: 9Rank: 9

UID
354297
好友
0
蠻牛幣
473
威望
0
注冊時間
2020-11-3
在線時間
167 小時
最后登錄
2020-11-24

馬上注冊,結交更多好友,享用更多功能,讓你輕松玩轉社區。

您需要 登錄 才可以下載或查看,沒有帳號?注冊帳號

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);
    }
}












回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 注冊帳號

本版積分規則

内蒙古麻将app 3d试机号查询 国标麻将单机版1.3 金沙棋牌游戏张公岭 快乐双彩最新开奖公告 快三青海走势图推荐号 天开眼麻将手机版下 哈灵麻将官网ios 大富豪棋牌游戏平台 白小姐图库 十一选五今天开奖结果 彩金捕鱼 血战麻将极品是什么 兴动哈尔滨麻将外挂 腾游棋牌娱乐 云南快乐10APP 河南快3app