53.网络通信-Unity网络类-WWWFrom类
53.1 知识点
WWWFrom 类的作用
作用:在使用
WWW
类下载数据的基础上,如果需要上传数据,则需要结合WWWFrom
类使用。WWWFrom
主要用于集成数据,可以设置上传的参数或者二进制数据。在结合WWWFrom
上传数据时,主要使用的请求类型是Post
,使用Http
协议进行上传处理。注意:
使用WWW
结合WWWFrom
上传数据通常需要与后端程序制定上传规则。
WWWFrom 类的常用方法和变量
- 主要使用方法,相关变量很少使用,重点讲解方法。
WWWForm 构造函数
//1.WWWForm:构造函数
WWWForm wWWForm = new WWWForm();
WWWForm.AddBinaryData 添加二进制数据
//2.AddBinaryData:添加二进制数据
wWWForm.AddBinaryData()
WWWForm.AddField 添加字段
//3.AddField:添加字段
wWWForm.AddField()
WWW 结合 WWWFrom 对象来异步上传数据
IEnumerator UpLoadData()
{
WWWForm wWWForm = new WWWForm();
//上传的数据 对应的后端程序 必须要有处理的规则 才能生效
//比如写入一些字段 比如字符串 年龄 图片二进制数据
wWWForm.AddField("Name", "MrTao", Encoding.UTF8);
wWWForm.AddField("Age", 99);
//传入 字段 字节数组 上传后的文件名 媒体类型
wWWForm.AddBinaryData("file", File.ReadAllBytes(Application.streamingAssetsPath + "/test.png"), "testtest.png", "application/octet-stream");
WWW www = new WWW("http://192.168.1.101:8000/HTTPRoot/", wWWForm);
yield return www;
if (www.error == null)
{
print("上传成功");
//上传成功可以打印内容
//www.bytes
}
else
print("上传失败" + www.error);
}
StartCoroutine(UpLoadData());
总结
- 使用
WWW
结合WWWFrom
上传数据需要与后端服务器配合指定上传规则。 - 上传的数据需要后端知道如何处理。
- 该方式适用于制作短连接游戏的前端网络层,可以对
WWW
进行二次封装,用于上传自定义消息给对应的 Web 服务器。
53.2 知识点代码
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;
public class Lesson53_网络通信_Unity网络类_WWWFrom类 : MonoBehaviour
{
void Start()
{
#region 知识点一 WWWFrom类的作用
//上节课学习了使用WWW类来下载数据
//如果想要使用WWW上传数据时,就需要配合WWWFrom类进行使用了
//而WWWFrom主要就是用于集成数据的,我们可以设置上传的参数或者2进制数据
//当结合WWWFrom上传数据时
//它主要用到的请求类型是Post
//它使用Http协议进行上传处理
//注意:
//使用WWW结合WWWFrom上传数据一般需要配合后端程序制定上传规则
#endregion
#region 知识点二 WWWFrom类的常用方法和变量
//该类当中我们主要就使用方法,相关变量很少使用,我们主要就着重讲解方法
//1.WWWForm:构造函数
WWWForm wWWForm = new WWWForm();
//2.AddBinaryData:添加二进制数据
//wWWForm.AddBinaryData()
//3.AddField:添加字段
//wWWForm.AddField()
#endregion
#region 知识点三 WWW结合WWWFrom对象来异步上传数据
StartCoroutine(UpLoadData());
#endregion
#region 总结
//WWW结合WWWFrom上传数据
//需要配合后端服务器来指定上传规则
//也就是说我们上传的数据,后端需要知道收到数据后应该如何处理
//通过这种方式我们没办法像C#类当中完成文件的上传
//但是该方式非常适合用于制作短连接游戏的前端网络层
//我们可以对WWW进行二次封装,专门用于上传自定义消息给对应的Web服务器
#endregion
}
#region 知识点三 WWW结合WWWFrom对象来异步上传数据
IEnumerator UpLoadData()
{
WWWForm wWWForm = new WWWForm();
//上传的数据 对应的后端程序 必须要有处理的规则 才能生效
//比如写入一些字段 比如字符串 年龄 图片二进制数据
wWWForm.AddField("Name", "MrTao", Encoding.UTF8);
wWWForm.AddField("Age", 99);
//传入 字段 字节数组 上传后的文件名 媒体类型
wWWForm.AddBinaryData("file", File.ReadAllBytes(Application.streamingAssetsPath + "/test.png"), "testtest.png", "application/octet-stream");
WWW www = new WWW("http://192.168.1.101:8000/HTTPRoot/", wWWForm);
yield return www;
if (www.error == null)
{
print("上传成功");
//上传成功可以打印内容
//www.bytes
}
else
print("上传失败" + www.error);
}
#endregion
}
53.3 练习题
在NetWWW管理器中封装发送HTTP消息的方法,方法可以传入TCP知识当中封装的BaseMessage对象,我们假设,服务器返回的内容为字节数组,该字节数组同样也是遵循客户端规则的继承自BaseMessage的对象
定义服务器所在路径,封装异步发送信息的协程方法
private string HTTP_SERVER_PATH = "http://192.168.1.101:8000/HTTPRoot/";
/// <summary>
/// 通过协程异步发送消息,并等待响应。
/// </summary>
/// <typeparam name="T">消息类型的泛型参数,必须是BaseMsg的派生类。</typeparam>
/// <param name="BaseMessage">要发送的消息对象。</param>
/// <param name="action">消息发送成功后要执行的动作。</param>
private IEnumerator SendMessageAsync<T>(BaseMessage BaseMessage, UnityAction<T> action) where T : BaseMessage
{
// 创建一个WWWForm来准备要发送的消息数据
WWWForm wWWForm = new WWWForm();
// 将消息数据以二进制形式添加到WWWForm中
wWWForm.AddBinaryData("BaseMessage", BaseMessage.Writing());
// 创建一个WWW对象并发送消息到HTTP服务器
WWW www = new WWW(HTTP_SERVER_PATH, wWWForm);
// 等待异步操作完成,即等待消息发送结束
yield return www;
// 检查是否有错误发生
if (www.error == null)
{
// 解析从服务器返回的消息,提取消息ID和消息长度
int index = 0;
int msgID = BitConverter.ToInt32(www.bytes, index);
index += 4;
int msgLength = BitConverter.ToInt32(www.bytes, index);
index += 4;
// 根据消息ID反序列化消息
BaseMessage baseMessage = null;
switch (msgID)
{
case 1001:
baseMessage = new PlayerMessage();
baseMessage.Reading(www.bytes, index);
break;
}
// 调用指定的动作,并将反序列化后的消息作为泛型参数传递
if (baseMessage != null)
action?.Invoke(baseMessage as T);
}
else
{
// 输出错误信息
Debug.LogError("发消息出问题" + www.error);
}
}
封装给外部使用发送信息的方法
/// <summary>
/// 发送消息的通用方法,通过协程异步发送消息并在接收响应后执行指定的动作。
/// </summary>
/// <typeparam name="T">消息类型的泛型参数,必须是BaseMsg的派生类。</typeparam>
/// <param name="baseMessage">要发送的消息对象。</param>
/// <param name="action">消息发送成功后要执行的动作。</param>
public void SendMessage<T>(BaseMessage baseMessage, UnityAction<T> action) where T : BaseMessage
{
// 启动协程异步发送消息
StartCoroutine(SendMessageAsync<T>(baseMessage, action));
}
53.4 练习题代码
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class NetWWWManager : BaseSingletonInMonoBehaviour<NetWWWManager>
{
private string HTTP_SERVER_PATH = "http://192.168.1.101:8000/HTTPRoot/";
/// <summary>
/// 提供给外部加载资源用的方法
/// </summary>
/// <typeparam name="T">资源的类型</typeparam>
/// <param name="path">资源的路径 http ftp file都支持</param>
/// <param name="action">加载结束后的回调函数 因为WWW是通过结合协同程序异步加载的 所以不能马上获取结果 需要回调获取</param>
public void LoadResource<T>(string path, UnityAction<T> action) where T : class
{
StartCoroutine(LoadResourceAsync<T>(path, action));
}
/// <summary>
/// 内部异步使用WWW加载资源用的协程方法
/// </summary>
/// <typeparam name="T">资源的类型</typeparam>
/// <param name="path">资源的路径 http ftp file都支持</param>
/// <param name="action">加载结束后的回调函数 因为WWW是通过结合协同程序异步加载的 所以不能马上获取结果 需要回调获取</param>
private IEnumerator LoadResourceAsync<T>(string path, UnityAction<T> action) where T : class
{
//声明www对象 用于下载或加载
WWW www = new WWW(path);
//等待下载或者加载结束(异步)
yield return www;
//优化的话可以让外部多传一个在加载时逻辑处理的委托回调
//如果没有错误 证明加载成功
if (www.error == null)
{
//根据T泛型的类型 决定使用哪种类型的资源 传递给外部
if (typeof(T) == typeof(AssetBundle))
{
action?.Invoke(www.assetBundle as T);
}
else if (typeof(T) == typeof(Texture))
{
action?.Invoke(www.texture as T);
}
else if (typeof(T) == typeof(AudioClip))
{
action?.Invoke(www.GetAudioClip() as T);
}
else if (typeof(T) == typeof(string))
{
action?.Invoke(www.text as T);
}
else if (typeof(T) == typeof(byte[]))
{
action?.Invoke(www.bytes as T);
}
//自定义一些类型 可能需要将bytes 转换成对应的类型来使用
}
//如果错误 就提示别人
else
{
//优化的话可以让外部多传一个在错误时委托回调
Debug.LogError("www加载资源出错" + www.error);
}
}
/// <summary>
/// 发送消息的通用方法,通过协程异步发送消息并在接收响应后执行指定的动作。
/// </summary>
/// <typeparam name="T">消息类型的泛型参数,必须是BaseMsg的派生类。</typeparam>
/// <param name="baseMessage">要发送的消息对象。</param>
/// <param name="action">消息发送成功后要执行的动作。</param>
public void SendMessage<T>(BaseMessage baseMessage, UnityAction<T> action) where T : BaseMessage
{
// 启动协程异步发送消息
StartCoroutine(SendMessageAsync<T>(baseMessage, action));
}
/// <summary>
/// 通过协程异步发送消息,并等待响应。
/// </summary>
/// <typeparam name="T">消息类型的泛型参数,必须是BaseMsg的派生类。</typeparam>
/// <param name="BaseMessage">要发送的消息对象。</param>
/// <param name="action">消息发送成功后要执行的动作。</param>
private IEnumerator SendMessageAsync<T>(BaseMessage BaseMessage, UnityAction<T> action) where T : BaseMessage
{
// 创建一个WWWForm来准备要发送的消息数据
WWWForm wWWForm = new WWWForm();
// 将消息数据以二进制形式添加到WWWForm中
wWWForm.AddBinaryData("BaseMessage", BaseMessage.Writing());
// 创建一个WWW对象并发送消息到HTTP服务器
WWW www = new WWW(HTTP_SERVER_PATH, wWWForm);
// 等待异步操作完成,即等待消息发送结束
yield return www;
// 检查是否有错误发生
if (www.error == null)
{
// 解析从服务器返回的消息,提取消息ID和消息长度
int index = 0;
int msgID = BitConverter.ToInt32(www.bytes, index);
index += 4;
int msgLength = BitConverter.ToInt32(www.bytes, index);
index += 4;
// 根据消息ID反序列化消息
BaseMessage baseMessage = null;
switch (msgID)
{
case 1001:
baseMessage = new PlayerMessage();
baseMessage.Reading(www.bytes, index);
break;
}
// 调用指定的动作,并将反序列化后的消息作为泛型参数传递
if (baseMessage != null)
action?.Invoke(baseMessage as T);
}
else
{
// 输出错误信息
Debug.LogError("发消息出问题" + www.error);
}
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com