在搞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!!!