[Like] 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;
}
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.Any5001);
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);
//解析数据 编码自己调整暂定为默认 依客户端传过来的编码而定
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;
}
}
///
/// 发送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(“UDPClient发送了=”+message);
//关闭
udpSend.Close();
}
private void OnApplicationQuit()
{
OnDestroy();
}
private void OnDestroy()
{
print(“关闭UDP连接”);
if (RecviveThread != null)
{
RecviveThread.Abort();
}
if (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);
}
}






工程案例能否提供依稀啊, 里边有各种报错!!
引用: kuanyidai 发表于 2020-12-2 17:18
工程案例能否提供依稀啊, 里边有各种报错!!

可能会有“”的字符串里里多了一些\\\\\\,删一下,如果有其它报错,可以私聊我
测试成功了。  如果多个命令的话 就需要些多个  UDP_Send?  
引用: kuanyidai 发表于 2020-12-3 16:31
测试成功了。  如果多个命令的话 就需要些多个  UDP_Send?

只需要调用UDP管理器类都的UDP_Manager.m_instance.UDPSendMessage方法就可以实现发送,注意下里面的ip和端口即可
12-7修改了帖子发布产生的的多余字符串,并测试了代码,如果有问题欢迎留言
我想问一下,在发布IPAD端以后,UDP发送是没有问题的,但是熄屏以后再点亮屏幕 UDP通信就会中断? 你有没有好的办法, 我听说有一个解决办法, 按钮点击打开UDP,发送UDP字符串,发送完毕以后再关闭UDP命令,这样就不怕熄屏跟后台操作了?
引用: kuanyidai 发表于 2020-12-19 20:46
我想问一下,在发布IPAD端以后,UDP发送是没有问题的,但是熄屏以后再点亮屏幕 UDP通信就会中断? 你有没有 ...

首先要检测一下UDP的连接状态,UDPData.UDPClient.Client.Connected,如果为false应该就是有地方调用了UDPData.UDPClient.Close(); ,看一下是否调用了OnDestroy()方法,主要针对熄屏以后打印一下,看一下它是什么原因导致的中断
6666666666666666666666
  • 10# pmrssn
  • 2021-3-5 13:41:30
这个好,感谢楼主分享
pc-->android行吗?
  • 12# 萌宝
  • 2021-3-11 13:45:19
6666666666666666666666666666666666666
引用: HongHu881 发表于 2021-3-10 17:16
pc-->android行吗?

理论上是没问题的,我也没测试过,如果可以也给我留言一下吧
  • 14# 月马
  • 2021-4-27 16:43:28
引用: LikeIsMe 发表于 2020-12-20 10:17
首先要检测一下UDP的连接状态,UDPData.UDPClient.Client.Connected,如果为false应该就是有地方调用了UD ...

这个我是检测程序的状态,如果处于挂起就断掉链接,程序为激活状态,如果UDP没有链接就重新链接,好像解决了这问题,不知道对不对。