Unity网络编程之UDPClent实现局域网通信
【前言】
UDP通信,是我最开始做一个视频同步的功能开始学习的,随后就开始使用UDPClent做网络传输,我的理解中,UDPClent是system.net网络程序集下的一个关于UDP的网络管理器,底层也是和TCP一样的Socket相关功能封装,多得也不说了,下面我直接放出代码,实现一个简单的发送、接收案例。【基于UDPClent封装的网络管理器类——UDP_Manager】接收是同一端口全部接收,所以收发注意一下端口号,收发的端口号要一致。
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;
public class UDPManager : MonoBehaviour
{
class UDPData
{
private 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 UDPManager m_instance;
string receiveData = string.Empty;
private Action<string> ReceiveCallBack = null;
private Thread RecviveThread;
private void Awake()
{
if (m_instance == null)
{
m_instance = this;
DontDestroyOnLoad(this);
}
else
{
Destroy(this);
}
}
private void Start()
{
//开启接收消息线程
ThreadRecvive();
}
private void Update()
{
if (ReceiveCallBack != null &&
!string.IsNullOrEmpty(receiveData))
{
//调用处理函数去数据进行处理
ReceiveCallBack(receiveData);
//使用之后清空接受的数据
receiveData = string.Empty;
}
}
public void SetReceiveCallBack(Action<string> action)
{
ReceiveCallBack = action;
}
UDPData data;
///
/// 开始线程接收
///
public void ThreadRecvive()
{
//开一个新线程接收UDP发送的数据
RecviveThread = new Thread(() =>
{
//实例化一个IPEndPoint,任意IP和对应端口 端口自行修改
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any,5001);
UdpClient udpReceive = new UdpClient(endPoint);
data = new UDPData(endPoint, udpReceive);
//开启异步接收
udpReceive.BeginReceive(CallBackRecvive, data);
})
{
//设置为后台线程
IsBackground = true
};
//开启线程
RecviveThread.Start();
}
///
/// 异步接收回调
///
///
private void CallBackRecvive(IAsyncResult ar)
{
try
{
//将传过来的异步结果转为我们需要解析的类型
UDPData state = ar.AsyncState as UDPData;
IPEndPoint ipEndPoint = state.EndPoint;
//结束异步接受 不结束会导致重复挂起线程卡死
byte[] data = state.UDPClient.EndReceive(ar, ref ipEndPoint);
//解析数据 编码自己调整暂定为默认 依客户端传过来的编码而定
receiveData = Encoding.Default.GetString(data);
Debug.Log(receiveData);
//数据的解析再Update里执行 Unity中Thread无法调用主线程的方法
//再次开启异步接收数据
state.UDPClient.BeginReceive(CallBackRecvive, state);
}
catch (Exception e)
{
Debug.LogError(e.Message);
throw;
}
}
///
/// 发送UDP信息
///
/// 发送地址
/// 发送端口
/// 需要发送的信息
public void UDPSendMessage(string remoteIP, int remotePort, string message)
{
//将需要发送的内容转为byte数组 编码依接收端为主,自行修改
//byte[] sendbytes = Encoding.GetEncoding("GB2312").GetBytes(message);
byte[] sendbytes = Encoding.Default.GetBytes(message);
IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Parse(remoteIP), remotePort);
UdpClient udpSend = new UdpClient();
//发送数据到对应目标
udpSend.Send(sendbytes, sendbytes.Length, remoteIPEndPoint);
print("IP="+remoteIP + ";remotePort="+ remotePort + ";message=" + message);
//关闭
udpSend.Close();
}
//private void OnApplicationQuit()
//{
// OnDestroy();
//}
private void OnDestroy()
{
print("关闭UDP连接");
if (RecviveThread != null)
{
RecviveThread.Abort();
}
if (data !=null || data.UDPClient != null)
{
data.UDPClient.Close();
}
}
}
【测试发送功能——UDP_Send】
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UDPSend : MonoBehaviour
{
UDPManager manager;
// Start is called before the first update
void Start()
{
//获取到UDPManager 脚本内部自己开启了线程无需再次开启
manager = GetComponent<UDPManager>();
if (manager == null)
{
manager = gameObject.AddComponent<UDPManager>();
}
//设置好解析的方法
}
// Update is called once per
void Update()
{
if (Input.GetMouseButtonDown(1))
{
manager.UDPSendMessage("192.168.3.113”, 5002","点击了鼠标右键!!");
//print("点击了鼠标右键");
}
}
}
【测试接收功能——UDP_Receive】
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UDPRecvice : MonoBehaviour
{
void Start()
{
//获取到UDPManager 脚本内部自己开启了线程无需再次开启
UDPManager manager = GetComponent<UDPManager>();
if (manager == null)
{
manager = gameObject.AddComponent<UDPManager>();
}
//设置好解析的方法
manager.SetReceiveCallBack(ReceiveUDPMessage);
manager.ThreadRecvive();
}
void ReceiveUDPMessage(string receiveData)
{
//接下来就看自己如何解析了
Debug.Log(receiveData);
}
}