53.WWWFrom类

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

×

喜欢就点赞,疼爱就打赏