在搞OSS对象存储中发现了自身的一些不足(http协议原理 跟 流的概念)

最近在搞OSS对象存储,发现了自身的一些不足,趁着有空在此做个总结,希望能够帮助到大家!!!

首先解释下OSS,Object Storage Service(对象存储服务),一般的云公司,都会提供OSS的。说的通俗点,就是远程服务器提供一定的空间专门来存储文件的,这些文件可以直接通过url任意时间,任意地点访问。
而把文件存储到OSS空间里,就是使用的http协议。OSS中的Bucket就是Windows系统下的文件夹。

一、http原理

我们知道http协议是基于TCP/IP协议的,也就是说,通过http进行数据传输,首先需要进行TCP连接。TCP连接需要进行三次握手,断开连接需要进行四次挥手。

关于TCP的三次握手跟四次挥手,话不多说,直接推荐,人家已经写的很好了。 无需我多说废话。
TCP的三次握手
TCP的四次挥手
握手要稍微了解一下的,不然可能无法理解下面的keep-alive。
想了解https原理的,推荐彻底搞懂https原理

http请求信息

http的请求报文,就是发送给服务端的信息,主要包含三个部分:请求行、请求头部、请求数据
(借用别人的图)

请求行主要包含请求方法(GET,POST,PUT,DELETE),URL跟http协议版本
请求头部:

在这里,稍微了解一下
Accept指的是,本次请求,接受哪些格式的文件
Accept-Encoding :接受的文件压缩格式
Host :域名,主机名

比较重要的请求头部
Connection :采用的连接方式
Content-Type(请求编码方式): application/x-www-form-urlencoded(只能是键值对方式) application/form-data(可以包含文件)
Content-Length(请求数据长度): 35
Authorization(认证):当我们需要访问其他公司提供的服务接口时,必须要有这个签名认证。

有兴趣可以了解一下http协议版本

在1.0版本下,每次发送一个请求时都要进行一次TCP三次握手,然后再进行数据传输,TCP连接消耗成本较高。为了能够复用TCP的连接,
因而诞生了1.1版本,主要的变化就是可以进行持久连接,也就是说,一次TCP连接可以发送多个http请求,但服务端仍然一次只能处理一个请求,依次进行。只需设置请求头部的Connection的值为keep-alive,即可。如果超过一定的时间没有继续发送http请求,TCP连接会自动关闭,当然也可以设置主动关闭。
至于未来的2.0版本,最大的变化便是增加双工模式,使用多路复用技术,也就是说不仅客户端能够同时发送多个请求,服务端也能同时处理多个请求
2.0版本的还没捂热,3.0已经来了,学不动了呀。至于3.0是个什么情况,小爷也不知道。

http响应信息

http的响应报文就是服务端给http请求的回应信息,主要包含状态行、响应头部、响应数据。
1 状态行:协议版本、状态码、简要描述,例如:HTTP/1.1 200 OK
常见的状态码:200,一切正常 400,客户端错误 404,相关资源文件未找到 500,服务端错误

2 响应头部:例如:Content-Type: text/plain,json等

3 响应数据:即服务器回应客户端的内容。如果我们请求网页,则返回网页内容,如果只是单纯请求数据,则返回相应的数据。

二、.NET中提供的相应的API

WebRequest,HttpWebRequest, WebResponse,HttpWebResponse
这几个类做爬虫的话,也经常用到的。可能很多人被这几个类搞混了。鄙人也是的,怎么这么多类,好像还有什么WebClient等。。。

WebRequest类,这个类是一个抽象类,是对URI发出请求而进行了一种抽象,跟动物是对狗狗、猫咪、小老鼠等的一种抽象是一个道理。
面向对象的思想很是伟大,他来源于真实世界的抽象,当然我们也可以用面向对象的思想来反观世界。
很是精彩!!!

HttpWebRequest类,这个类是WebRequest类的派生类,专门用于进行http特定的实现。里面有相应的属性和方法。
WebResponse HttpWebResponse 同理。

//请求
HttpWebRequest request =(HttpWebRequest)WebRequest.Create("//www.contoso.com/");
request.KeepAlive = false;//设置是否为持久连接
request.Method = "POST";
string authorization="";//获取认证签名
request.Headers.Add("Authorization", authorization);//将认证签名添加到请求头部

Stream requestStream = request.GetRequestStream();//获取请求流

string postData = "nickName=打游戏也要有梦想&hobby=coding";//添加请求数据
ASCIIEncoding encoding = new ASCIIEncoding ();
byte[] byte1 = encoding.GetBytes (postData);
request.ContentType = "application/x-www-form-urlencoded";//请求编码方式
request.ContentLength = byte1.Length;//请求数据长度

requestStream.Write (byte1, 0, byte1.Length);//给请求流中添加请求数据
requestStream.Close();//关闭请求流


//响应
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();//获取响应流
StreamReader readStream = new StreamReader (responseStream, Encoding.UTF8);//读取响应流
string responseText=readStream.ReadToEnd();//响应信息
response.Close ();
readStream.Close ();


三、流的概念

http协议传输的数据其实就是通过流来传输的。流这东西,有数据流、文件流、读写流等,的确很是抽象,不知道到底是个什么东西,搞了半天,发现被这个高大上的名字给忽悠了。
所谓的流呢,其实就是字节序列,就是字节数组。搞后端的应该都知道,需要将返回的对象进行序列化后再传输到前端。其中的序列化,便是将对象转为字节序列(流),来进行传输。这么说吧,http传输的数据都是通过流来传输的。
那大家可能会有个问题,http协议中是怎么上传下载文件的,通过类HttpWebRequest,我们得到一个对象,接下来我们得到请求流,然后把文件添加到这个请求流里,便可以了;同理,下载文件也是如此,得到响应流,然后将流写入到一个新建的文件流便可以了。

//通过http上传文件,只需在请求流中写入需要上传的文件    fileStream为需要上传的文件转为流的形式
Stream requestStream = request.GetRequestStream();//请求流
//上传文件
byte[] buffer = new byte[64 * 1024];//设置缓存区大小,据说64KB最好(只是据说,没有亲测)
int read = fileStream.Read(buffer, 0, buffer.Length);
while (read > 0)
{
    requestStream.Write(buffer, 0, red);//在请求流中继续写入文件流
    read = fileStream.Read(buffer, 0, buffer.Length);
}
//关闭流
fileStream.Close();
requestStream.Close();
//通过http下载文件,只需将响应流中写入到新建的文件流中
Stream responseStream = response.GetResponseStream();//获取响应流

string fileName="";//新建的文件名,包含路径名称和文件名以及后缀
FileStream fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write);//创建文件流
byte[] buffer = new byte[64 * 1024];//设置缓存区大小,据说64KB最好(只是据说,没有亲测)
int totalSize = 0;//文件总大小
int size = responseStream.Read(buffer, 0, buffer.Length);
while (size > 0)
{
    totalSize += size;
    fileStream.Write(buffer, 0, size);//将响应流中写入到新建的文件流中
    size = responseStream.Read(buffer, 0, buffer.Length);
}
fileStream.Close();
responseStream.Close();

四、认证签名

关于签名的,肯定会涉及到一些加密算法,base64,sha1,md5等这些算法,这些算法并不需要我们去掌握,.NET已经提供了相应的API,只需会调用即可,没必要去深究到底是怎么实现的。
使用其他公司提供的接口服务,都会有相应的公钥和私钥,按照官网文档来生成相应的认证签名就可以了。然后将认证签名添加到请求头部里,便可以访问其他公司提供的接口服务了。
一般生成签名的接口需要在自己的服务端自己写一个,得到的签名与其他公司服务端生成的签名进行比对。

五、最后

最后祝大家国庆快乐,玩得开心,国庆Happy!!!