【Unity网络编程知识】C#的 Http相关类学习

news2025/4/15 10:13:44

1、搭建HTTP服务器

  • 使用别人做好的HTTP服务器软件,一般作为资源服务器时使用该方式(学习阶段建议使用)
  • 自己编写HTTP服务器应用程序,一般作为Web服务器或者短连接游戏服务器时使用该方式(工作后由后端程序员来做)

1.1 使用hfs搭建HTTP服务器,双击打开运行即可

1.2 添加服务器访问文件夹

右键打开添加文件夹

选择自己需要设置的访问文件夹

 1.3 设置允许访问和上传权限

移到目标文件夹右键选择Properties

创建允许访问用户凭证

 设置访问权限

设置上传权限

 设置删除权限

2、C#的Http关键类介绍

2.1 HttpWebRequest类

重要方法

1)Create 创建新的WebRequest,用于进行HTTP相关操作

2)Abort  如果正在进行文件传输,用此方法可以终止传输

3)GetRequestStream 获取用于上传的流

4)GetResponse 返回HTTP服务器响应

5)Begin/EndGetRequestStream 异步获取用于上传的流

6)Begin/EndGetResponse 异步获取返回的HTTP服务器响应

重要成员

1)Credentials通信凭证,设置为NetworkCredential对象

2)PreAuthenticate是否随请求发送一个身份验证标头,一般需要进行身份验证时需要将其设置为true

3)Headers构成标头的名称/值对的集合

4)ContentLength发送信息的字节数上传信息时需要先设置该内容长度

5)ContentType在进行POST请求时,需要对发送的内容进行内容类型的设置

6)Method操作命令设置

  •  WebRequestMethods.Http类中的操作命令属性
  • Get             获取请求,一般用于获取数据
  • Post           提交请求,一般用于上传数据,同时可以获取
  • Head          获取和Get一致的内容,只是只会返回消息头,不会返回具体内容
  • Put             向指定位置上传最新内容
  • Connect     表示与代理一起使用的HTTPCONNECT协议方法,该代理可以动态切换到隧道
  • MkCol        请求在请求 URI(统一资源标识符)指定的位置新建集合

2.2 HttpWebResponse类

重要方法

1)Close:释放所有资源

2)GetResponseStream:返回从FTP服务器下载数据的流

重要成员

1)ContentLength:接受到数据的长度

2)ContentType:接受数据的类型

3)StatusCode:HTTP服务器下发的最新状态码

4)StatusDescription:HTTP服务器下发的状态代码的文本

5)BannerMessage:登录前建立连接时HTTP服务器发送的消息

6)ExitMessage:HTTP会话结束时服务器发送的消息

7)LastModified:HTTP服务器上的文件的上次修改日期和时间

2.3 NetworkCredential

3、Http下载数据

3.1 检测资源可用性

            //利用Head请求参型,获取信息
            //1.创建HTTP通讯用连接对象HttpWebRequest对象
            HttpWebRequest req = HttpWebRequest.Create(new Uri("https://t7.baidu.com/it/u=2604797219,1573897854&fm=193&f=GIF")) as HttpWebRequest;
            //2.设置请求类型或其它相关参数
            req.Method = WebRequestMethods.Http.Head;
            req.Timeout = 2000;
            //3.发送请求,获取响应结果HttpWebResponse对象
            HttpWebResponse res = req.GetResponse() as HttpWebResponse;
            
            //4.判断资源是否存在
            if (res.StatusCode == HttpStatusCode.OK)
            {
                print("文件存在且可用");
                print(res.ContentLength);
                print(res.ContentType);

                res.Close();
            }
            else
            {
                print("文件不可用" + res.StatusCode);
            }

3.2 下载资源

            //1.创建HTTP通讯用连接对象HttpWebRequest对象
            HttpWebRequest req2 = HttpWebRequest.Create(new Uri("https://t7.baidu.com/it/u=2604797219,1573897854&fm=193&f=GIF")) as HttpWebRequest;
            //2.设置请求类型或其它相关参数
            req2.Method = WebRequestMethods.Http.Get;
            req2.Timeout = 3000;
            //3.发送请求,获取响应结果HttpWebResponse对象
            HttpWebResponse res2 = req2.GetResponse() as HttpWebResponse;
            //4.获取响应数据流,写入本地路径
            if (res2.StatusCode == HttpStatusCode.OK)
            {
                print(Application.persistentDataPath);
                using (FileStream fileStream = File.Create(Application.persistentDataPath + "/httpDownLoad.jpg"))
                {
                    Stream downLoadStream = res2.GetResponseStream();
                    byte[] bytes = new byte[2048];
                    //读取数据
                    int contentLength = downLoadStream.Read(bytes, 0, bytes.Length);
                    //一点一点写入本地
                    while (contentLength > 0)
                    {
                        fileStream.Write(bytes, 0, contentLength);
                        contentLength = downLoadStream.Read(bytes, 0, bytes.Length);
                    }
                    fileStream.Close();
                    downLoadStream.Close();
                    res2.Close();
                }
                print("下载成功");
            }
            else
            {
                print("下载失败" + res2.StatusCode);
            }

3.3 Get请求类型携带额外信息

1)协议部分

2)域名或公网IP部分

3)端口部分(默认80不需要写)

4)虚拟目录部分

5)参数部分

        //我们在进行HTTP通信时,可以在地址后面加一些额外参数传递给服务端
        //一般在和短连接游戏服务器通讯时,需要携带额外信息
        // 举例:
        //http://www.aspxfans.com:8080/news/child/index.boardID=5&ID=24618&page=1
        //这个链接可以分成几部分
        //1.协议部分:取决于服务器端使用的哪种协议
        //http:     //一 普通的http超文本传输协议
        //https:    //一 加密的超文本传输协议

        //2.域名部分:
        //www.aspxfans.com
        //也可以填写服务器的公网IP地址

        //3.端口部分:
        //8080
        //可以不写,如果不写默认为80

        //4.虚拟目录部分:
        //news/child/
        //域名后的/开始,到最后一个/之前的部分

        //5.文件名部分:
        // index.asp
        //?之前的最后一个 / 后的部分

        // 6.参数部分:
        //boardID=5&ID=24618&page=1
        //?之后的部分就是参数部分,多个参数一&分隔开
        //这里有三个参数
        //boardID = 5
        //ID = 24618
        //page = 1

        //我们在和服务端进行通信时,只要按照这种规则格式进行通信,就可以传递参数给对象
        //主要可用于:
        //1.web网站服务器
        //2.游戏短连接服务器
        //等

4、Http上传文件

4.1 上传文件到HTTP资源服务器需要遵守的规则

        //上传文件时内容的必备规则
        //  1:ContentType ="multipart/form-data;boundary=边界字符串";

        //  2:上传的数据必须按照格式写入流中
        //  --边界字符串
        //  Content - Disposition:form - data; name = "字段名字,之后写入的文件2进制数据和该字段名对应"; filename = "传到服务器上使用的文件名"
        //  Content - Type:application / octet - stream(由于我们传2进制文件所以这里使用2进制)
        //  空一行
        //  (这里直接写入传入的内容)
        //  --边界字符串--

        //  3:保证服务器允许上传
        //  4:写入流前需要先设置ContentLength内容长度

4.2 上传文件

        //1.创建HttpWebRequest对象
        HttpWebRequest req = HttpWebRequest.Create("http://192.168.1.25:8000/HttpServer/") as HttpWebRequest;
        //2.相关设置(请求类型,内容类型,超时,身份验证等)
        req.Method = WebRequestMethods.Http.Post;
        req.ContentType = "multipart/form-data;boundary=MrZhou";
        req.Timeout = 50000;

        req.Credentials = new NetworkCredential("ZT", "zt123");
        req.PreAuthenticate = true;

        //3.按格式拼接字符串并且转为字节数组之后用于上传
        //3-1.文件数据前的头部信息
        //  --边界字符串
        //  Content-Disposition:form-data;name="字段名字,之后写入的文件2进制数据和该字段名对应";filename="传到服务器上
        //  Content-Type:application/octet-stream(由于我们传2进制文件所以这里使用2进制)
        string head = "--MrZhou\r\n" +
            "Content-Disposition:form-data;name=\"file\";filename=\"http上传的文件.jpg\"\r\n" +
            "Content-Type:application/octet-stream\r\n\r\n";
        //头部拼接字符串规则信息的字节数组
        byte[] headBytes = Encoding.UTF8.GetBytes(head);

        //3-2.结束的边界信息
        // --边界字符串--
        byte[] endBytes = Encoding.UTF8.GetBytes("\r\n--MrZhou--\r\n");

        //4.写入上传流
        //4-1.设置上传长度
        //4-2.先写入前部分头部信息
        //4-3.再写入文件数据
        //4-4.在写入结束的边界信息
        using (FileStream localFileStream = File.OpenRead(Application.streamingAssetsPath + "/test.png"))
        {
            //4-1.设置上传长度
            //总长度 是前部分字符串 + 文件本身大小 + 后部分边界字符串
            req.ContentLength = headBytes.Length + localFileStream.Length + endBytes.Length;
            //用于上传的流
            Stream upLoadStream = req.GetRequestStream();
            //4-2.先写入前部分头部信息
            upLoadStream.Write(headBytes, 0, headBytes.Length);
            //4-3.再写入文件数据
            byte[] bytes = new byte[2048];
            int contentLength = localFileStream.Read(bytes, 0, bytes.Length);
            while(contentLength > 0)
            {
                upLoadStream.Write(bytes, 0, contentLength);
                contentLength = localFileStream.Read(bytes, 0, bytes.Length);
            }
            //4-4.在写入结束的边界信息
            upLoadStream.Write(endBytes, 0, endBytes.Length);

            upLoadStream.Close();
            localFileStream.Close();
        }

        //5.上传数据,获取响应
        HttpWebResponse res = req.GetResponse() as HttpWebResponse;
        if(res.StatusCode == HttpStatusCode.OK)
        {
            print("上传通讯成功");
        }
        else
        {
            print("上传失败" + res.StatusCode);
        }

5、Http管理类

using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Events;

public class HttpMgr
{
    private static HttpMgr instance = new HttpMgr();
    public static HttpMgr Instance => instance;

    //private string HTTP_PATH = "https://t7.baidu.com/it/";
    private string HTTP_PATH = "http://192.168.1.25:8000/HttpServer/";

    private string USER_NAME = "ZT";
    private string PASS_WORD = "zt123";

    /// <summary>
    /// 下载指定文件到本地指定路径中
    /// </summary>
    /// <param name="url">远程文件路径</param>
    /// <param name="localPath">本地路径</param>
    /// <param name="action">下载结束后的回调函数</param>
    public async void DownLoadFile(string url, string localFilePath, UnityAction<HttpStatusCode> action = null)
    {
        HttpStatusCode result = HttpStatusCode.OK;
        await Task.Run(() =>
        {
            try
            {
                //判断文件是否存在 Head
                //1.创建HTTP连接对象
                HttpWebRequest req = HttpWebRequest.Create(url) as HttpWebRequest;
                //2.设置请求类型 和 其他相关参数
                req.Method = WebRequestMethods.Http.Head;
                req.Timeout = 2000;
                //3.发送请求
                HttpWebResponse res = req.GetResponse() as HttpWebResponse;

                //存在才下载
                if(res.StatusCode == HttpStatusCode.OK)
                {
                    res.Close();
                    //下载文件
                    //1.创建HTTP连接对象
                    req = HttpWebRequest.Create(url) as HttpWebRequest;
                    //2.设置请求类型 和 其他相关参数
                    req.Method = WebRequestMethods.Http.Get;
                    req.Timeout = 2000;
                    //3.发送请求
                    res = req.GetResponse() as HttpWebResponse;
                    //4.存储数据到本地
                    if(res.StatusCode == HttpStatusCode.OK)
                    {
                        //存储数据
                        using (FileStream fileStream = File.Create(localFilePath))
                        {
                            Stream downLoadStream = res.GetResponseStream();
                            byte[] bytes = new byte[2048];
                            int contentLength = downLoadStream.Read(bytes, 0, bytes.Length);
                            while (contentLength > 0)
                            {
                                fileStream.Write(bytes, 0, contentLength);
                                contentLength = downLoadStream.Read(bytes, 0, bytes.Length);
                            }
                            fileStream.Close();
                            downLoadStream.Close();
                        }
                        result = HttpStatusCode.OK;
                    }
                    else
                    {
                        result = res.StatusCode;
                    }
                }
                else
                {
                    result = res.StatusCode;
                }

                res.Close();

            }
            catch (WebException e)
            {
                result = HttpStatusCode.InternalServerError;
                Debug.LogError("文件下载失败" + e.Message + e.Status);
            }
        });

        action?.Invoke(result);

    }

    /// <summary>
    /// 上传文件
    /// </summary>
    /// <param name="fileName">传到远端服务器上的文件名</param>
    /// <param name="localFilePath">本地的文件路径</param>
    /// <param name="action">上传结束后的回调函数</param>
    public async void UpLoadFile(string fileName, string localFilePath, UnityAction<HttpStatusCode> action = null)
    {
        HttpStatusCode result = HttpStatusCode.BadGateway;

        await Task.Run(() =>
        {
            try
            {
                HttpWebRequest req = HttpWebRequest.Create(HTTP_PATH) as HttpWebRequest;
                req.Method = WebRequestMethods.Http.Post;
                req.ContentType = "multipart/form-data;boundary=MrZhou";
                req.Timeout = 50000;
                req.Credentials = new NetworkCredential(USER_NAME, PASS_WORD);
                req.PreAuthenticate = true;

                //拼接字符串头部
                string head = "--MrZhou\r\n" +
                            "Content-Disposition:form-data;name=\"file\";filename=\"{0}\"\r\n" +
                            "Content-Type:application/octet-stream\r\n\r\n";
                //替换文件名
                head = string.Format(head, fileName);
                Debug.Log(head);
                byte[] headBytes = Encoding.UTF8.GetBytes(head);

                //尾部的边界字符串
                byte[] endBytes = Encoding.UTF8.GetBytes("\r\n--MrZhou--\r\n");

                using(FileStream localStream =  File.OpenRead(localFilePath))
                {
                    //设置长度
                    req.ContentLength = headBytes.Length + localStream.Length + endBytes.Length;
                    //写入流
                    Stream upLoadStream = req.GetRequestStream();
                    //写入头部
                    upLoadStream.Write(headBytes, 0, headBytes.Length);
                    //写入上传文件
                    byte[] bytes = new byte[2048];
                    int contentLength = localStream.Read(bytes, 0, bytes.Length);
                    while (contentLength > 0)
                    {
                        upLoadStream.Write(bytes, 0, contentLength);
                        contentLength = localStream.Read(bytes, 0, bytes.Length);
                    }
                    //写入尾部
                    upLoadStream.Write(endBytes, 0, endBytes.Length);

                    upLoadStream.Close();
                    localStream.Close();

                }

                HttpWebResponse res = req.GetResponse() as HttpWebResponse;

                //让外部去处理结果
                result = res.StatusCode;
                res.Close();

            }
            catch (WebException e)
            {
                Debug.LogError("上传失败" + e.Message + e.Status);
            }
        });

        action?.Invoke(result);

    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2334074.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot企业级开发之【用户模块-更新用户头像】

功能如下所示&#xff1a; 我们先看一下接口文档&#xff1a; 为什么头像是一串字符串呢&#xff1f;因为我们是将头像图片放到第三方去存储&#xff0c;比如&#xff1a;阿里云等 开发思路&#xff1a; 实操&#xff1a; 1.controller 注意!这里使用【PatchMapping】注解…

DAPP实战篇:使用ethersjs连接智能合约并输入地址查询该地址余额

本系列目录 专栏:区块链入门到放弃查看目录-CSDN博客文章浏览阅读400次。为了方便查看将本专栏的所有内容列出目录,按照顺序查看即可。后续也会在此规划一下后续内容,因此如果遇到不能点击的,代表还没有更新。声明:文中所出观点大多数源于笔者多年开发经验所总结,如果你…

网络流量管理-流(Flow)

1. 传统网络的问题&#xff1a;快递员送信模式 想象你每天要寄100封信给同一个朋友&#xff0c;传统网络的处理方式就像一个固执的快递员&#xff1a; 每封信都单独处理&#xff1a;检查地址、规划路线、盖章、装车…即使所有信的目的地、收件人都相同&#xff0c;也要重复100…

每日文献(十一)——Part two

今天从第四章&#xff1a;快速RCNN&#xff0c;方法细节开始介绍。 目录 四、快速RCNN&#xff1a;方法细节 4.1 快速R-CNN回顾 4.2 对抗网络设计 4.2.1 遮挡的对抗空间信息损失 4.2.2 对抗空间Transformer网络 4.2.3 对抗融合 五、实验 5.1 实验设置 5.2 PASCAL VOC…

Laravel 实现 队列 发送邮件功能

一. 什么是队列 在构建 Web 应用程序时&#xff0c;你可能需要执行一些任务&#xff0c;例如解析文件&#xff0c;发送邮件&#xff0c;大量的数据计算等等&#xff0c;这些任务在典型的 Web 请求期间需要很长时间才能执行。 庆幸的是&#xff0c;Laravel 可以创建在后台运行…

一、绪论(Introduction of Artificial Intelligence)

写在前面&#xff1a; 老师比较看重的点&#xff1a;对问题的概念本质的理解&#xff0c;不会考试一堆运算的东西&#xff0c;只需要将概念理解清楚就可以&#xff0c;最后一个题会出一个综合题&#xff0c;看潜力&#xff0c;前面的部分考的不是很深&#xff0c;不是很难&…

Web攻防—SSRF服务端请求伪造Gopher伪协议无回显利用

前言 重学Top10的第二篇&#xff0c;希望各位大佬不要见笑。 SSRF原理 SSRF又叫服务端请求伪造&#xff0c;是一种由服务端发起的恶意请求&#xff0c;SSRF发生在应用程序允许攻击者诱使服务器向任意域或资源发送未经授权的请求时。服务器充当代理&#xff0c;执行攻击者构造…

【时时三省】(C语言基础)选择结构程序综合举例

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 下面综合介绍几个包含选择结构的应用程序。 例题1&#xff1a; 写一程序&#xff0c;判断某一年是否为闰年。 程序1&#xff1a; 先画出判别闰年算法的流程图&#xff0c;见下图用变量le…

File 类 (文件|文件夹操作)

一、File 类 1.1 前言 在 JDK 中 通过 java.io.File 类&#xff0c;可以实现操作系统重文件|文件夹的创建、删除、查看、重命名等操作。 1.2 File 类构造方法 File 一共提供了四个构造方法&#xff0c;都是有参构造。其中最常使用的是 File(String) 和 File(String, String)…

Hadoop文件操作指南:深入解析文件操作

1 Hadoop文件系统概述 Hadoop分布式文件系统(HDFS)是Hadoop生态的核心存储组件&#xff0c;专为大规模数据集设计&#xff0c;具有高容错性和高吞吐量特性。 HDFS核心特性: 分布式存储&#xff1a;文件被分割成块(默认128MB)分布存储多副本机制&#xff1a;每个块默认3副本&…

STM32 HAL库之EXTI示例代码

外部中断按键控制LED灯 在main.c中 HAL_Init(); 初始化Flash&#xff0c;中断优先级以及HAL_MspInit函数&#xff0c;也就是 stm32f1xx_hal.c 中 HAL_StatusTypeDef HAL_Init(void) {/* Configure Flash prefetch */ #if (PREFETCH_ENABLE ! 0) #if defined(STM32F101x6) || …

《TCP/IP网络编程》学习笔记 | Chapter 23:IOCP

《TCP/IP网络编程》学习笔记 | Chapter 23&#xff1a;IOCP 《TCP/IP网络编程》学习笔记 | Chapter 23&#xff1a;IOCP通过重叠 I/O 理解 IOCPepoll 和 IOCP 的性能比较实现非阻塞模式的套接字以纯重叠 I/O 方式实现回声服务器端重新实现客户端测试从重叠 I/O 模型到 IOCP 模型…

CAD导入arcgis中保持面积不变的方法

1、加载CAD数据&#xff0c;选择面数据&#xff0c;如下&#xff1a; 2、加载进来后&#xff0c;右键导出数据&#xff0c;导出成面shp数据&#xff0c;如下&#xff1a; 3、选择存储路径&#xff0c;导出面后计算面积&#xff0c;如下&#xff1a; 4、与CAD中的闭合线面积核对…

rustdesk自建服务器怎么填写客户端配置信息

目录 # id、api、中继都怎么填&#xff1f;rustdesk程序启动后服务不自动启动 # id、api、中继都怎么填&#xff1f; rustdesk程序启动后服务不自动启动 完全退出RudtDesk程序&#xff08;右下角托盘区有的话&#xff0c;需要右键点退出&#xff09; 创建windows服务&#xff…

c++进阶之----智能指针

1.概念 在 C 中&#xff0c;智能指针是一种特殊的指针类型&#xff0c;它封装了裸指针&#xff08;raw pointer&#xff09;的行为&#xff0c;并通过 RAII&#xff08;Resource Acquisition Is Initialization&#xff0c;资源获取即初始化&#xff09;机制自动管理动态分配的…

六、测试分类

设计测试用例 万能公式&#xff1a;功能测试性能测试界面测试兼容性测试安全性测试易用性测试 弱网测试&#xff1a;fiddler上行速率和下行速率 安装卸载测试 在工作中&#xff1a; 1.基于需求文档来设计测试用例&#xff08;粗粒度&#xff09; 输入字段长度为6~15位 功…

AI编程案例拆解|基于机器学习XX评分系统-前端篇

文章目录 1. 定价使用DeepSeek估价小红书调研 2. 确定工作事项利用DeepSeek生成具体工作事项 3. 和客户沟通约会议沟通确定内容样式 4. 前端部分设计使用DeepSeek生成UI设计在Cursor中生成并提问前置条件开始编程 关注不迷路&#xff0c;励志拆解100个AI编程、AI智能体的落地应…

java数组06:Arrays类

Arrays类 数组的工具类java.util. Arrays 由于数组对象本身并没有什么方法可以供我们调用,但API中是了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作。 查看JDK帮助文档 Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用…

TQTT_KU5P开发板教程---实现流水灯

文档实现功能介绍 本文档是学习本开发板的基础&#xff0c;通过设置计数器使led0到led7依次闪烁&#xff0c;让用户初步认识vivado基本的开发流程以及熟悉项目的创建。本开发板的所有教程所使用的软件都是vivado2024.1版本的。可以根据网上的教程下载与安装。 硬件资源 此次教程…

Model Context Protocol(MCP)模型上下文协议

Model Context Protocol&#xff08;MCP&#xff09;模型上下文协议 前言一、什么是MCP二、MCP的作用三、MCP与Function call对比四、构建一个简单的MCP DEMO环境准备实现MCP Server运行 ServerMCP Client端配置验证 总结 前言 在Agent时代&#xff0c;将Agent确立为大模型未来…