應用層
應用層
負責應用程序之間的數據溝通-----協議都是用戶自己定的
自定制協議:
結構化數據傳輸
序列化:
將數據對象以指定的協議(數據格式)進行可用于持久化存儲或者數據傳輸時的數據組織
例如在分布式的系統中,需要把對象從網絡的一端傳輸到另外一端;而網絡中數據是以二進制流的方式來傳遞的 ;此時對象的序列化就是完成把對象轉化成對應二進制流的方式;反序列化則是把二進制流轉化為對象數據的方式。
反序列化:
將二進制數據串按照指定的協議進行解析獲取到各個數據對象
序列化的方式:
- Json:JavaScript Object Notation, 是一種輕量級的數據交換格式,把對象的狀態序列化成為字符串 {屬性名:值}格式的字符串,移動端通訊常用數據格式。
- protobuf是Google開發的開源項目。protobuf是一種串行化的數據結構信息,類似xml。主要用于消息傳輸中消息格式規范,數據存儲。與xml相比,protobuf更小、更快、更簡單、更少歧義、方便生成消息存取類。
知名協議
HTTP-----超文本傳輸協議
URL:統一資源定位符(網址)
URL格式:
協議名稱://用戶名:密碼@服務器地址:端口/資源路徑?查詢字符串#片段標識符
查詢字符串(用戶提交的數據)中若包含特殊字符則需要進行URL編碼,因為在URL中特殊字符具有特殊含義。用戶提交的數據中若有特殊字符要避免這種二義性
urlencode:將特殊字符每一個字節轉換成為16進制數字的字符串,并且在前邊加上%
urldecode:%2 -('2'-'0')<<4+b-'0'
HTTP協議
HTTP三點注意事項
- HTTP是無連接:無連接的含義是限制每次連接只處理一個請求。服務器處理完客戶的請求,并收到客戶的應答后,即斷開連接。采用這種方式可以節省傳輸時間。
- HTTP是媒體獨立的:這意味著,只要客戶端和服務器知道如何處理的數據內容,任何類型的數據都可以通過HTTP發送。客戶端以及服務器指定使用適合的MIME-type內容類型。
- HTTP是無狀態:HTTP協議是無狀態協議。無狀態是指協議對于事務處理沒有記憶能力。缺少狀態意味著如果后續處理需要前面的信息,則它必須重傳,這樣可能導致每次連接傳送的數據量增大。另一方面,在服務器不需要先前信息時它的應答就較快。
HTTP協議格式
1.首行:
以空格進行間隔,分了三個部分
1-1請求首行:
- 請求方法
- URL
- 協議版本
請求方法
HTTP1.0定義了三種請求方法:GET: 獲取資源,提交數據在URL中存放,沒有正,POST:傳輸實體主體,提交數據在正文中出現,有正文,HEAD(獲得報文頭部,文件有多長)等其他方法。
協議版本
0.9/1.0/1.1/1.2-------各個版本之間的新特性
1-2響應首行
- 協議版本
- 響應狀態碼
- 狀態碼描述信息
常見的狀態碼, 比如 200(OK), 404(Not Found), 403(Forbidden,認證失敗), 302(Redirect, 重定向), 502(Bad Gateway,壞的網關)
2. 頭部
都是一個個以冒號空格形式組成的鍵值對,這些鍵值對之間以\r\n進行間隔
Conter-Length(標志正文有多長,解決粘包問題)/Content-Type(正文類型)/Referer(跳轉位置)/Cookie/Set-Cookie/Location(重定向位置)/Transfer-Encoding(是否進行分塊傳輸)
HTTP響應頭消息
3. 空行
\r\n間隔頭部與正文
4. 正文
http協議是一個在傳輸層基于tcp協議實現的應用層協議,在傳輸層默認使用80端口,使用字符串明文傳輸
HTTP 協議的 8 種請求類型介紹
HTTP 協議中共定義了八種方法或者叫“動作”來表明對 Request-URI 指定的資源的不同操作方式,具體介紹如下:
- OPTIONS:返回服務器針對特定資源所支持的HTTP請求方法。也可以利用向Web服務器發送’*'的請求來測試服務器的功能性。
- HEAD:向服務器索要與GET請求相一致的響應,只不過響應體將不會被返回。這一方法可以在不必傳輸整個響應內容的情況下,就可以獲取包含在響應消息頭中的元信息。
- GET:向特定的資源發出請求。
- POST:向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在請求體中。POST請求可能會導致新的資源的創建和/或已有資源的修改。
- PUT:向指定資源位置上傳其最新內容。
- DELETE:請求服務器刪除 Request-URI 所標識的資源。
- TRACE:回顯服務器收到的請求,主要用于測試或診斷。
- CONNECT:HTTP/1.1 協議中預留給能夠將連接改為管道方式的代理服務器。
雖然 HTTP 的請求方式有 8 種,但是我們在實際應用中常用的也就是 get 和 post,其他請求方式也都可以通過這兩種方式間接的來實現。
最簡單的HTTP服務器
/* *實現最簡單的http服務器1.http實際是一個tcp服務器,不過應用數據的處理是http協議格式2.處理數據的時候:1. 獲取http頭部(首行+頭部)2.獲取數據3.根據頭部中的請求處理數據3.接受到瀏覽器的請求之后,打印一下請求的數據,并且響應<html><body><h1>Hello World</h1></body></html>*/
#include<sstream>
#include"tcpsocket.hpp"
int main()
{TcpSocket sock;CHECK_RET(sock.Socket());CHECK_RET(sock.Bind("0.0.0.0",2502));CHECK_RET(sock.Listen());while(1){TcpSocket clisock;std::string cliip;uint16_t cliport;bool ret =sock.Accept(clisock,cliip,cliport);if(ret == false){continue;}std::string buf;clisock.Recv(buf);std::cout<<"req:["<<buf<<"]\n";std::string body;body = "<html><body><h1>Hello World</h1></body></html>";//正文std::string first_line = "HTTP/1.1 200 OK \r\n";//頭部std::stringstream header;header << "Content-Length:" << body.size() << "\r\n";//正文長度header << "Content-Type:" << "text/html\r\n";//正文類型std::string blank ="\r\n";//空行clisock.Send(first_line);clisock.Send(header.str());clisock.Send(blank);clisock.Send(body);clisock.Send(body);clisock.Close();}return 0;
}