前面我們實現(xiàn)了TCP服務(wù)器和客戶端的簡單應(yīng)用,接下來我們實現(xiàn)一個基于TCP協(xié)議的應(yīng)用協(xié)議,那就是HTTP超文本傳輸協(xié)議
1 、 ** HTTP****協(xié)議簡介**
超文本傳輸協(xié)議(Hyper Text Transfer Protocol),簡稱HTTP,是一種基于TCP的應(yīng)用層協(xié)議,也是目前為止最為流行的應(yīng)用層協(xié)議之一,可以說HTTP協(xié)議是萬維網(wǎng)的基石。
HTTP是一種客戶端請求、服務(wù)器應(yīng)答式的應(yīng)用層傳輸協(xié)議,也就是說服務(wù)器端是不可能主動向客戶端發(fā)送數(shù)據(jù)的。在網(wǎng)絡(luò)正常的情況下請求和響應(yīng)都是一一對應(yīng)的。而這個請求和響應(yīng)也就是后端開發(fā)人員經(jīng)??吹降腞equest和Response。
首先,我們來看客戶器端的請求,HTTP請求報文由請求行、請求頭、空白行以及請求體組成。其報文格式如下:
我們來說一說請求行,它由請求方法字段、URL字段和HTTP協(xié)議版本字段3個字段組成,它們用空格分隔。需要理解的是請求方法,HTTP協(xié)議的請求方法有GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT幾種。先對常用的幾種說明如下:
- GET 方法 ,意思是獲取URL指定的資源,這個請求方式是最簡單的也是最常用的。使用GET 方法時,可以將請求參數(shù)和對應(yīng)的值附加在 URI 后面,利用一個問號(“?”)將資源的URI和請求參數(shù)隔開,參數(shù)之間使用與符號(“&”)隔開,因此傳遞參數(shù)長度也受到了限制,而且與隱私相關(guān)的信息也直接暴露在URI中。比如/index.jsp?username=holmofy&password=123123
- HEAD 方法, 與GET用法相同,但沒有響應(yīng)體,使用場合沒有GET多。比如下載前使用HEAD發(fā)送請求,通過ContentLength響應(yīng)字段,來了解網(wǎng)絡(luò)資源的大??;或者通過LastModified響應(yīng)字段來判斷本地緩存資源是否要更新。
- POST 方法, 一般用提交信息或數(shù)據(jù),請求服務(wù)器進(jìn)行處理(例如提交表單或者上傳文件)。表單使用POST相對GET來說還是比較隱秘的,而且GET的URL有長度限制,而上傳大文件就必須要使用POST了。
- OPTIONS 方法, 該方法用于請求服務(wù)器告知其支持哪些其他的功能和方法。通過OPTIONS 方法,可以詢問服務(wù)器具體支持哪些方法,或者服務(wù)器會使用什么樣的方法來處理一些特殊資源??梢哉f這是一個探測性的方法,客戶端通過該方法可以在不訪問服務(wù)器上實際資源的情況下就知道處理該資源的最優(yōu)方式。這個選項在跨域HTTP請求的情況出現(xiàn)的比較多,這里有一篇關(guān)于跨域請求的文章,其中有一張圖很好的解釋了什么是跨域HTTP請求。
客戶端發(fā)出HTTP請求,服務(wù)端接收后,會向客戶端發(fā)送響應(yīng)信息。所以接下來,我們來看看服務(wù)器端的響應(yīng)報文。HTTP響應(yīng)報文由響應(yīng)行、響應(yīng)頭、空白行以及響應(yīng)體組成。其報文格式如下:
在響應(yīng)報文中,非常重要的就是響應(yīng)行,其中響應(yīng)行中最重要的就是HTTP的狀態(tài)碼。HTTP協(xié)議中狀態(tài)碼有三位數(shù)字組成,第一位數(shù)字定義了響應(yīng)的類別,有以下五種:
- 1XX : 信息提示。表示請求已被服務(wù)器接受,但需要繼續(xù)處理,范圍為100~101。
- 2XX : 請求成功。服務(wù)器成功處理了請求。范圍為200~206。
- 3XX:客戶端重定向。重定向狀態(tài)碼用于告訴客戶端瀏覽器,它們訪問的資源已被移動,并告訴客戶端新的資源位置??蛻舳耸盏街囟ㄏ驎匦聦π沦Y源發(fā)起請求。范圍為300~305。
- 4XX : 客戶端信息錯誤??蛻舳丝赡馨l(fā)送了服務(wù)器無法處理的東西,比如請求的格式錯誤,或者請求了一個不存在的資源。范圍為400~415。
- 5XX:服務(wù)器出錯??蛻舳税l(fā)送了有效的請求,但是服務(wù)器自身出現(xiàn)錯誤,比如Web程序運行出錯。范圍是500~505。
我們開發(fā)過程有一些狀態(tài)碼比較常見,我們對其簡單說明如下:
2 、 ** HTTP****服務(wù)器端的設(shè)計**
我們已經(jīng)對基于RAW API的TCP應(yīng)用有了了解。我們在實現(xiàn)TCP服務(wù)器的實驗時就提到過對于更復(fù)雜的應(yīng)用和應(yīng)用層協(xié)議只是在功能上的差別,從實現(xiàn)的結(jié)構(gòu)及流程來說是完全一致的。所以對于實現(xiàn)HTTP服務(wù)器需要使用到的函數(shù)及整個操作流程我們就不再敘述了。重點說一說不同的地方。
首先HTTP服務(wù)器是基于TCP的,所以其我們先將其當(dāng)作TCP服務(wù)器來實現(xiàn)。需要注意的是,HTTP協(xié)議有其專門的操作端口:80。所以我們設(shè)計服務(wù)器時需要使用這個端口。
在這里,我們設(shè)計一個簡單的HTTP服務(wù)器,當(dāng)客戶端連接到服務(wù)器之后,如果收到的是html請求,則返回一個我們預(yù)先設(shè)定好的網(wǎng)頁。正常返回這個網(wǎng)頁,HTTP的功能就完成了,HTTP服務(wù)器會主動斷開與客戶端的連接。
3 、 ** TTP****服務(wù)器實現(xiàn)**
既然是基于TCP的HTTP服務(wù)器,我們佷顯然依然按照TCP服務(wù)器的結(jié)構(gòu)來實現(xiàn)。我們依然將其劃分為三個部分來實現(xiàn)。首先要實現(xiàn)的是HTTP服務(wù)器的初始化。
1 /* HTTP服務(wù)器初始化配置*/
2 void Http_Server_Initialization(void)
3 {
4 struct tcp_pcb *pcb = NULL;
5
6 /* 生成一個新的TCP控制塊 */
7 pcb = tcp_new();
8
9 /* 控制塊綁定到本地IP和對應(yīng)端口 */
10 tcp_bind(pcb, IP_ADDR_ANY, TCP_HTTP_SERVER_PORT);
11
12 /* 服務(wù)器進(jìn)入偵聽狀態(tài) */
13 pcb = tcp_listen(pcb);
14
15 /* 注冊服務(wù)器accept回調(diào)函數(shù) */
16 tcp_accept(pcb, HttpServerAccept);
17
18 }
從上面的代碼不難看出,與TCP服務(wù)器的初始化一樣:建立控制塊,為控制塊綁定本地IP和端口,服務(wù)器監(jiān)聽控制塊同時注冊接收處理回調(diào)函數(shù)。所以接下來就是實現(xiàn)接收處理回調(diào)函數(shù)。
1 /* HTTP接收回調(diào)函數(shù),客戶端建立連接后,本函數(shù)被調(diào)用 */
2 static err_t HttpServerAccept(void *arg, struct tcp_pcb *pcb, err_t err)
3 {
4 /*注冊HTTP服務(wù)器回調(diào)函數(shù)*/
5 tcp_recv(pcb, HttpServerCallback);
6
7 return ERR_OK;
8 }
客戶端連接成功后就會調(diào)用接收處理回調(diào)函數(shù)。該函數(shù)為tcp_accept_fn類型,注冊到了監(jiān)聽控制塊的accept字段。在這個函數(shù)中,我們需要注冊HTTP服務(wù)器處理函數(shù)。其功能就由這個函數(shù)決定。
1 /* HTTP服務(wù)器信息處理回調(diào)函數(shù) */
2 static err_t HttpServerCallback(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
3 {
4 char *data = NULL;
5
6 if (p != NULL)
7 {
8 /* 更新接收窗口 */
9 tcp_recved(pcb, p->tot_len);
10 data = p->payload;
11
12 /* 如果是http請求,返回html信息,否則無響應(yīng) */
13 if(p->len >=3 && data[0] == 'G'&& data[1] == 'E'&& data[2] == 'T')
14 {
15 tcp_write(pcb, htmlMessage, sizeof(htmlMessage), 1);
16 }
17 else
18 {
19
20 }
21 pbuf_free(p);
22 tcp_close(pcb);
23 }
24 else if (err == ERR_OK)
25 {
26 return tcp_close(pcb);
27 }
28 return ERR_OK;
29 }
這個HTTP服務(wù)器非常簡單,我們只是實現(xiàn)了GET方法。也就是說,收到客戶端的html請求后,我們檢測其要求,如果是GET方法,我們就返回預(yù)先設(shè)定好的網(wǎng)頁,否則無返回。然后關(guān)閉這一連接。如果我們想要實現(xiàn)更復(fù)雜的功能,或者需要支持HTTP協(xié)議的其他方法,只需要擴(kuò)展這個函數(shù)就可以了。
4 、 結(jié)論
HTTP協(xié)議是一種使用非常廣泛的協(xié)議,其基于TCP基礎(chǔ)上運行,所以在我們前面已經(jīng)實現(xiàn)TCP服務(wù)器及客戶端的情況下,開發(fā)HTTP服務(wù)器應(yīng)用就顯得簡單了。在這一篇我們基于LwIP實現(xiàn)了一個簡單的HTTP服務(wù)器應(yīng)用,我們并對其進(jìn)行了簡單的測試,雖然我們只是實現(xiàn)了GET方法,但經(jīng)測試設(shè)計是正確的。如果需要設(shè)計其他方法的HTTP應(yīng)用只需在此基礎(chǔ)上添加即可。
-
服務(wù)器
+關(guān)注
關(guān)注
12文章
8958瀏覽量
85084 -
HTTP
+關(guān)注
關(guān)注
0文章
499瀏覽量
30980 -
TCP
+關(guān)注
關(guān)注
8文章
1347瀏覽量
78933 -
傳輸協(xié)議
+關(guān)注
關(guān)注
0文章
72瀏覽量
11423 -
LwIP
+關(guān)注
關(guān)注
2文章
85瀏覽量
27055
發(fā)布評論請先 登錄
相關(guān)推薦
評論