您好,登錄后才能下訂單哦!
1http簡(jiǎn)單介紹
http超文本傳輸協(xié)議:host主機(jī)地址:port端口/url
host會(huì)被DNS服務(wù)器 解析成IP地址,所以有時(shí)候可以直接用域名,
http默認(rèn)訪問(wèn)80端口,https默認(rèn)訪問(wèn)443端口
大致流程就是:瀏覽器輸入地址后,首先和web服務(wù)器建立tcp連接,
然后瀏覽器發(fā)送http請(qǐng)求報(bào)文, web服務(wù)器響應(yīng)處理這個(gè)報(bào)文,
然后給他回復(fù)一個(gè)響應(yīng),然后服務(wù)器主動(dòng)斷開(kāi)連接。
2http請(qǐng)求報(bào)文格式
首先第一個(gè)就是請(qǐng)求的方法,方法有一下這些:
GET,POST,HEAD,PUT,DELETE,OPTIONS,TRACE,CONNECT;
1GET
在瀏覽器輸入的網(wǎng)址,瀏覽器就會(huì)發(fā)送GET的http報(bào)文請(qǐng)求。
如果不寫url 默認(rèn)就是 "/" 服務(wù)器 可根據(jù)這個(gè)響應(yīng)對(duì)應(yīng)的頁(yè)面.
頭部信息就包含一些重要的請(qǐng)求信息,如主機(jī)地址.
瀏覽器版本 , 手機(jī)的頁(yè)面就是根據(jù)這個(gè)去做的.
GET 攜帶參數(shù)是在url里面的, POST是攜帶在包體里面的.
包體成為body,請(qǐng)求頭部叫做head。
GET傳遞參數(shù),格式 /url?username=xxx&passwd=bbb 通過(guò)問(wèn)號(hào)解析參數(shù)部分
url的傳遞參數(shù)是有限制的,每個(gè)瀏覽器限制都不一樣。url不允許有回車換行
2POST
POST也是一個(gè)請(qǐng)求操作,他的數(shù)據(jù)參數(shù)攜帶在http請(qǐng)求的body里面。
所有的參數(shù)都不允許有回車換行的存在, 很多時(shí)候如果必須要攜帶
回車換行的話,必須先把數(shù)據(jù)轉(zhuǎn)換成base64編碼,因?yàn)樗鼪](méi)有回車換成.他是解決網(wǎng)絡(luò)傳輸?shù)某S梅椒ā?/span>
3http響應(yīng)報(bào)文格式
1狀態(tài)碼:請(qǐng)求是否成功,狀態(tài)碼描述:成功或失敗的原因
有時(shí)候訪問(wèn)一網(wǎng)頁(yè) 會(huì)出現(xiàn)404,這個(gè)404就是這個(gè)狀態(tài)碼.
4http數(shù)據(jù)傳輸模式
1傳輸中兩個(gè)重要的參數(shù): 寫在頭里面
transfer-encoding:identity,chunked表示當(dāng)前這個(gè)body是什么協(xié)議發(fā)過(guò)來(lái)的
content-length:length:數(shù)據(jù)包的長(zhǎng)度
2identity 直接發(fā)送模式,length在后面表示數(shù)據(jù)長(zhǎng)度
3chunked 模式,后面跟的是每一個(gè)chunk包 [包頭,包數(shù)據(jù)]
包頭:第一個(gè)字節(jié)表示一個(gè)ASSIC數(shù)據(jù),第二個(gè)字節(jié)也是ASSIC數(shù)據(jù)
兩個(gè)字節(jié)加起來(lái),組成一個(gè)16進(jìn)制數(shù)據(jù)。
后面兩個(gè)字節(jié),固定的0d0a(回車換行符)兩個(gè)字節(jié)這4個(gè)字節(jié)就是一個(gè)chunk的包頭,
后面的數(shù)據(jù)包 根據(jù)前面的兩個(gè)字節(jié)來(lái)決定。數(shù)據(jù)包的結(jié)束標(biāo)志是
30 0d 0a 30ascll碼代表的是0
也就是說(shuō)chunk包的結(jié)束:是遇到一個(gè)為等于0的chunk結(jié)束。
然后把這個(gè)包整合一下,形成完整的數(shù)據(jù)。
5http狀態(tài)碼和表
/*
{
[100] = "Continue",
[101] = "Switching Protocols",
[200] = "OK",
[201] = "Created",
[202] = "Accepted",
[203] = "Non-Authoritative Information",
[204] = "No Content",
[205] = "Reset Content",
[206] = "Partial Content",
[300] = "Multiple Choices",
[301] = "Moved Permanently",
[302] = "Found",
[303] = "See Other",
[304] = "Not Modified",
[305] = "Use Proxy",
[307] = "Temporary Redirect",
[400] = "Bad Request",
[401] = "Unauthorized",
[402] = "Payment Required",
[403] = "Forbidden",
[404] = "Not Found",
[405] = "Method Not Allowed",
[406] = "Not Acceptable",
[407] = "Proxy Authentication Required",
[408] = "Request Time-out",
[409] = "Conflict",
[410] = "Gone",
[411] = "Length Required",
[412] = "Precondition Failed",
[413] = "Request Entity Too Large",
[414] = "Request-URI Too Large",
[415] = "Unsupported Media Type",
[416] = "Requested range not satisfiable",
[417] = "Expectation Failed",
[500] = "Internal Server Error",
[501] = "Not Implemented",
[502] = "Bad Gateway",
[503] = "Service Unavailable",
[504] = "Gateway Time-out",
[505] = "HTTP Version not supported",
}
*/
6使用http_parmer解析 URL讀取 然后返回給客戶端
//解析我們的http報(bào)文 http_parser p; http_parser_init(&p,HTTP_REQUEST); http_parser_settings s; http_parser_settings_init(&s); //解析到了url 回調(diào) s.on_url = ws_on_url; //重置解析信息 init_ws_params(); // 解析器執(zhí)行。返回解析的字節(jié)數(shù) http_parser_execute(&p,&s,http_req,len); //設(shè)置回調(diào)函數(shù) switch (p.method) //報(bào)文響應(yīng)的方式 { case HTTP_GET: { int len_URL = filter_url(WS_HTTP.url); //訪問(wèn)的網(wǎng)頁(yè) if (strncmp("/", WS_HTTP.url, len_URL) == 0){ //訪問(wèn)test這個(gè)html strncpy(WS_HTTP.url, "www_root/index.html", strlen("www_root/index.html")); } else if (strncmp("/test", WS_HTTP.url, len_URL) == 0){ //訪問(wèn)默認(rèn)的url 根目錄 strncpy(WS_HTTP.url, "www_root/test.html", strlen("www_root/test.html")); } char* file_data = open_files(WS_HTTP.url); //發(fā)送報(bào)文 也就是響應(yīng)客戶端 //釋放內(nèi)存 free(file_data); } break; case HTTP_POST: break; } //end printf("\n"); 讀取文件 static char* open_files(char* filename) { //讀取這個(gè)文件 FILE* f = fopen(filename,"rb"); //文件大小 int file_size = 0; fseek(f,0,SEEK_END); file_size = ftell(f); //指針又到文件頭 fseek(f, 0, 0); char* file_data = malloc(file_size + 1); fread(file_data, file_size,1, f); file_data[file_size] = 0; fclose(f); return file_data; }
7響應(yīng)請(qǐng)求報(bào)文
//使用identity來(lái)發(fā)送響應(yīng)報(bào)文 static void write_ok_identity(int sock, char* body) { int len = strlen(body); //使用直接模式 transfer-encoding:identity char* send_line = malloc(len + 8096); memset(send_line, 0, sizeof(send_line)); //回應(yīng)http的頭 sprintf(send_line, "HTTP/1.1 %d %s\r\n", 200, "OK"); //設(shè)置頭部的一些信息 比如傳送模式 body的長(zhǎng)度 char* walk = send_line; //跳過(guò)這個(gè)頭部 walk = walk + strlen(walk); sprintf(walk,"transfer-encoding:%s\r\n","identity"); //body的長(zhǎng)度 walk = walk + strlen(walk); //頭結(jié)束 sprintf(walk, "content-length: %d\r\n\r\n0", len); //寫入數(shù)據(jù)部分 walk = walk + strlen(walk); sprintf(walk, "%s", body); //發(fā)送報(bào)文 響應(yīng) 給客戶端 send(sock, send_line, strlen(send_line), 0); free(send_line); walk = NULL; }
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。