HTTP请求以及文件下载

1.Http请求的概念

HTTP 请求是客户端向服务器发送的请求,用于获取特定资源或执行特定操作。它包含请求行、请求头部和请求体等部分,其中请求行包含请求的方法、URL 和协议版本,请求头部包含关于客户端请求的各种信息,请求体则包含需要传输给服务器的数据。

2.Http请求API的介绍

  • HttpListener

HttpListener 是 .NET Framework 提供的用于创建 HTTP 服务器以侦听传入 HTTP请求的类。
用法:
HttpListener httpListener;
httpListener = new HttpListener();

  • HttpClient

HttpClient 是 .NET Framework 提供的用于发送 HTTP 请求的类。它可以用于向服务器发送 GET、POST
等类型的请求,并处理服务器的响应。
用法:
HttpClient httpClient;
httpClient = new HttpClient();

  • httpListener.GetContextAsync

httpListener.GetContextAsync用于异步地获取传入的 HTTP 请求并返回一个HttpListenerContext 对象,在 HTTP 服务器中等待并处理客户端发送的请求。
用法:
var context = await httpListener.GetContextAsync();

  • HttpListenerContext

HttpListenerContext 类表示了收到的 HTTP 请求以及将要发送的 HTTP 响应。它是 HttpListener类的一部分,用于处理传入的 HTTP 请求并生成相应的响应。
用法:
HttpListenerContext context = awaithttpListener.GetContextAsync();

HttpListenerContext 的一些主要属性和方法:

Request:表示收到的 HTTP 请求。通过该属性,你可以获取请求的各种信息,如请求头、请求方法、请求体等。

Response:表示将要发送的 HTTP 响应。通过该属性,你可以设置要发送的响应的各种信息,如响应头、响应状态码、响应体等。

User:表示与请求关联的用户身份信息。可以使用该属性来获取关于用户的信息,如用户名、权限等。

ErrorStatus:表示在处理请求时发生的错误状态。如果请求处理过程中出现了错误,可以使用该属性来获取错误状态码和错误信息。

Abort():用于取消请求并关闭连接。如果在处理请求过程中发现无法继续处理或需要提前结束请求,可以调用该方法来取消请求并关闭连接。

  • context.Request.RawUrl

context.Request.RawUrl 是 HttpListenerRequest 对象的一个属性,用于获取客户端发送的原始 URL地址,不经过任何解析或编码。
用法:
var text = context.Request.RawUrl;

  • HttpListenerContext.Response

HttpListenerContext.Response 属性表示将要发送的 HTTP
响应。通过该属性,你可以设置要发送的响应的各种信息,如响应头、响应状态码、响应体等

  • stream.WriteAsync()

stream.WriteAsync() 方法能将数据写入到输出流中,从而将数据发送给客户端。
用法:
await stream.WriteAsync(data, 0, data.Length);//将data数组写入stream响应的输出流中

  • httpListener.GetContextAsync

在 .NET 中,HttpListener 类用于创建一个 HTTP 服务器,可以监听指定的 URL 地址,并处理客户端发送的 HTTP
请求。

  • context.Request.inputStream

context.Request.InputStream 提供了一个流对象,通过它可以读取客户端发送的请求主体数据。
用法:
Stream inpuStream = context.Request.InputStream;

  • inputStream.ReadAsync

InputStream.ReadAsync 是用于异步读取请求主体数据的方法,它返回一个表示异步读取操作的任务。
用法:
Stream inpuStream = context.Request.InputStream;
int length = await inpuStream.ReadAsync(readData, 0, readData.Length);

  • HttpListenerContext.Response

HttpListenerContext.Response 表示用于向客户端发送响应的对象。通过 Response
属性,你可以设置响应的状态码、响应头以及响应主体内容等信息。

  • stream.WriteAsync

stream.WriteAsync
是一个用于异步写入数据到流的方法。在C#中,流(Stream)是一种用于读取或写入序列数据的抽象概念。WriteAsync
方法允许你以异步的方式将数据写入到流中,而不会阻塞当前线程。
用法:
Stream stream = context.Response.OutputStream;
await stream.WriteAsync(data, 0, data.Length);

  • stream.close()

这个方法是用来关闭流的
用法:
var stream = context.Response.OutputStream;
stream.close()

  • HttpClient.GetAsync

HttpClient 类提供了发送 HTTP GET 请求的功能,GetAsync 方法允许你以异步的方式发送 GET 请求,并返回一个表示异步操作的 Task 对象,其中包含了表示请求响应的信息。
用法:
HttpResponseMessage response = await httpClient.GetAsync(page);

  • HttpResponseMessage

HttpResponseMessage 类表示 HTTP 响应消息。当你发送 HTTP 请求并收到响应时,服务器将返回一个 HttpResponseMessage 对象,其中包含了响应的状态码、头部信息和内容。你可以从中提取出响应的内容,并进行相应的处理。
用法:
string page = “http://127.0.0.1:8080/” + data;
HttpResponseMessage response = await httpClient.GetAsync(page);

  • response.Content.ReadAsStringAsync()

这个方法是用来异步读取响应内容的,response 是一个 HttpResponseMessage 对象,它包含了服务器响应的相关信息。
用法:
string text = await response.Content.ReadAsStringAsync();

  • HttpClient.PostAsync

PostAsync 方法用于以异步方式发送 HTTP POST 请求。你可以使用它来向服务器提交数据,通常用于提交表单数据或上传文件等操作。PostAsync 方法也返回一个表示异步操作的 Task 对象,你可以等待操作完成后处理响应。
用法:
string page = “http://127.0.0.1:8080/” + data;
StringContent stringContent = new StringContent(data);
var response = await httpClient.PostAsync(page, stringContent);

3.文件下载

1.客户端编写

if(data == "download")
{
    //下载文件 不同的处理
    //读取到的文件的数据
    byte[] fileData = await response.Content.ReadAsByteArrayAsync();
    string path = @"D:\Unity 2023.1.20f1c1\NetProject\DownLoad\unity.png";//路径要存在
    FileStream fileStream = new FileStream(path, FileMode.OpenOrCreate);
    await fileStream.WriteAsync(fileData, 0, fileData.Length);
    Debug.Log("下载完毕了");
}
else
{
    string str = await response.Content.ReadAsStringAsync();
    //使用 response.Content.ReadAsStringAsync() 方法读取 HTTP 响应的内容,并将其作为字符串返回
    Debug.Log($"post response:{str}");
}

2.服务端编写

if (text.Contains("/login")){
    byte[] data = Encoding.UTF8.GetBytes("登录成功");
    await stream.WriteAsync(data, 0, data.Length);//将data数组写入stream响应的输出流中
    stream.Close();
}

else if (text.Contains("/download"))
{
    //1.获取到路径下的文件 byte[]
    //2.将它读取后,响应给客户端
    //3.客户端拿到之后-》写到本地就可以了
    string path = @"D:\Unity 2023.1.20f1c1\NetProject\DB\unity.png";
    FileStream file = new FileStream(path, FileMode.Open);
    //创建一个文件流对象 file,用于读取文件中的数据
    byte[] data = new byte[file.Length];
    //创建一个大小为文件长度的字节数组 data
    int fileLength = await file.ReadAsync(data, 0,data.Length);
    //使用文件流的 ReadAsync() 方法异步从文件中读取数据
    //并将读取的数据存储到 data 数组
    Console.WriteLine("文件大小:" + fileLength);
    await stream.WriteAsync(data, 0, data.Length);
    //使用网络流 stream 的 WriteAsync() 方法异步将读取的文件数据写入到客户端
    stream.Close();
}

4.总体客户端编写

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using UnityEngine;

public class Client_Http : MonoBehaviour
{
    HttpClient httpClient;
    // Start is called before the first frame update
    void Start()
    {
        httpClient = new HttpClient();
        //Connect();
    }

    //public void Connect()
    //{
    //    throw new NotImplementedException();
    //}
    public async void Get(string data)
    {
        string page = "http://127.0.0.1:8080/" + data;
        HttpResponseMessage response = await httpClient.GetAsync(page);
        //发送 GET 请求到指定的 URL,并等待服务器的响应
        Debug.Log("http get:" + data);
        string text = await response.Content.ReadAsStringAsync();
        //将 HTTP 响应的内容异步读取为字符串
        Debug.Log("http get. 返回的数据是:"+ text);
    }
    public async void Post(string data)
    {
        string page = "http://127.0.0.1:8080/" + data;
        StringContent  stringContent = new StringContent(data);
        //将指定的字符串数据包装成 HTTP 请求的内容
        Dictionary<string,string> dct = new Dictionary<string,string>();
        dct["account"] = "xxx";
        dct["pwd"] = data;//“account” 键和 “pwd” 键分别赋予了值 “xxx” 和 data
        FormUrlEncodedContent content = new FormUrlEncodedContent(dct);
        //创建 HTTP 请求的内容对象 content
        //FormUrlEncodedContent类会将字典中的键值对数据编码为URL编码形式
        //以便将其作为 HTTP 请求的内容发送给服务器。
        var response = await httpClient.PostAsync(page, stringContent);
        if(data == "download")
        {
            //下载文件 不同的处理
            //读取到的文件的数据
            byte[] fileData = await response.Content.ReadAsByteArrayAsync();
            string path = @"D:\Unity 2023.1.20f1c1\NetProject\DownLoad\unity.png";
            FileStream fileStream = new FileStream(path, FileMode.OpenOrCreate);
            await fileStream.WriteAsync(fileData, 0, fileData.Length);
            Debug.Log("下载完毕了");
        }
        else
        {
            string str = await response.Content.ReadAsStringAsync();
            //使用 response.Content.ReadAsStringAsync() 方法读取 HTTP 响应的内容,并将其作为字符串返回
            Debug.Log($"post response:{str}");
        }
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {

            Get("login");
        }
        if (Input.GetKeyDown(KeyCode.S))
        {
            //Post("login");
            Post("download");
        }
    }
}

5.总体服务端编写

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace Server.Net
{
    internal class HttpServer
    {
        string page = "http://127.0.0.1:8080/";
        HttpListener httpListener;
        public void Start()
        {
            httpListener = new HttpListener();
            httpListener.Prefixes.Add(page);
            httpListener.Start(); 
            Accept();
            Console.WriteLine("http Server Start");
            HandleGet();
            HandlePost();
        }
        //处理Get请求
        public async void HandleGet()
        {
            var context = await httpListener.GetContextAsync();
            //监听 HTTP 请求
            var text = context.Request.RawUrl;
            //获取 HTTP 请求的原始 URL
            //可以获取到客户端发送的请求的详细信息,包括路径和查询参数等内容
            Console.WriteLine(text);
            var stream = context.Response.OutputStream;
            //表示响应的输出流,可以用于向客户端发送响应数据
            if (text.Contains("/login")){
                byte[] data = Encoding.UTF8.GetBytes("登录成功");
                await stream.WriteAsync(data, 0, data.Length);//将data数组写入stream响应的输出流中
                stream.Close();
            }

            else if (text.Contains("/download"))
            {
                //1.获取到路径下的文件 byte[]
                //2.将它读取后,响应给客户端
                //3.客户端拿到之后-》写到本地就可以了
                string path = @"D:\Unity 2023.1.20f1c1\NetProject\DB\unity.png";
                FileStream file = new FileStream(path, FileMode.Open);
                //创建一个文件流对象 file,用于读取文件中的数据
                byte[] data = new byte[file.Length];
                //创建一个大小为文件长度的字节数组 data
                int fileLength = await file.ReadAsync(data, 0,data.Length);
                //使用文件流的 ReadAsync() 方法异步从文件中读取数据
                //并将读取的数据存储到 data 数组
                Console.WriteLine("文件大小:" + fileLength);
                await stream.WriteAsync(data, 0, data.Length);
                //使用网络流 stream 的 WriteAsync() 方法异步将读取的文件数据写入到客户端
                stream.Close();
            }
            HandleGet();
            HandlePost();
        }
        public async void HandlePost()
        {
            HttpListenerContext context = await httpListener.GetContextAsync();监听 HTTP 请求
            Stream inpuStream = context.Request.InputStream;//表示请求的输入流,读取客户端发送的请求数据
            byte[] readData = new byte[context.Request.ContentLength64];
            //获取请求的正文长度,知道读取多少字节的数据
            //能创建一个对应长度的字节数组 readData
            //用于存储从请求输入流中读取的数据。
            int length = await inpuStream.ReadAsync(readData, 0, readData.Length);
            //异步读取请求的输入流,并将数据存储到 readData 字节数组中
            inpuStream.Close();

            string text = Encoding.UTF8.GetString(readData);
            Console.WriteLine("请求的内容:" + text);
            Stream stream = context.Response.OutputStream;
            if(text.Contains("login"))
            {
                Console.WriteLine("收到客户端的登录请求");
                byte[] data = Encoding.UTF8.GetBytes("登录成功");
                await stream.WriteAsync(data, 0, data.Length);
                stream.Close();
            }
        }
        //处理Post请求
        public void Accept()
        {
            
        }
    }
}

注意,前面关于Http请求API的介绍,不懂得可以看最后两个总体的客户端编写和服务端总体编写!!!

  • 31
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值