Http伺服器實現檔案上傳與下載(二)
一、引言
歡迎大家接著看我的部落格,如何大家有什麼想法的話回覆我哦,閒話不多聊了,接著上一講的內容來說吧,在上一節中已經講到了請求頭字串的解析,並且在解析中我我們已經獲取了url。就是上節中提到的/doing。當瀏覽器傳送了/doing請求後,這是的與伺服器的連線並沒有中斷,原因無他,就是瀏覽器等待接受服務端發來的資訊,然後他對資訊進行解析並顯示在瀏覽器介面上。在編寫Http伺服器時的C/S結構時,我只編寫服務端server,客戶端直接用現成的瀏覽器即可。
當服務端找到瀏覽器需要的內容的時候,現在服務端就需要把內容傳送給瀏覽器即可。但是在HTTP協議中,傳送具體內容之前,服務端還是要傳送一個響應頭,之前瀏覽器傳送的叫做請求頭,那麼服務端也要傳送一個響應頭告訴瀏覽器,說你的請求我接受或者拒接。拒絕的話之後就沒有具體實體內容傳送,否則再告訴瀏覽器說你請求的內容的格式是html或者text,或者是音訊等二進位制檔案等,並且告訴瀏覽器你請求內容的大小(這個非常重要)
二、HTTP協議
現在我們來看一下這個響應頭的一個例子,還是隻說明一些我們現在需要知道的,其他內容讀者可以自己去查詢相關的內容。
1 HTTP/1.1 200 OK 2 Server:(Unix) 3 Content-type:application/octet-stream 4 Content-length:65144369 5 Connection:Keep-Alive
在這個例子中的響應頭我們可以看到:
1)在第一行就告訴瀏覽器http協議的版本是1.1,狀態碼是200,意思是OK,就是說你的請求我同意了。
2)在第二行就是告知瀏覽器我伺服器的名字。
3)在第三行就是你請求的內容的格式是applicaiton/octet-stream,理解為二進位制流即可。
4)在第四行說明你請求內容的大小,單位是位元組。
5)第五行告訴瀏覽器是Keep-Alive連線方式。
在這個協議頭髮送給瀏覽器時,還是每行結尾都有一個回車換行\r\n。最後還是需要一個空行代表本響應頭結束。還有一些協議內容到用用到時再講,現在提出這幾項即可。當這個協議頭髮送給瀏覽器後,瀏覽器對其解析。然後等待真正的請求內容。當服務端把瀏覽器的請求的具體內容傳送完畢就關閉這個連線。
講到這裡基本一個請求響應結束了。那在這裡提一下如何處理大併發呢。其實在HTTP請求中,在每個URL請求中伺服器並不關心一些請求是否來著同個瀏覽器,伺服器做的只是有請求來臨就對其連線傳送資料,然後關閉資料。儘管可能來著同一客戶端上的請求有資料上的關係,但是服務端只是在傳送資料而已。所以對於同一個瀏覽器傳送的多個請求和不同瀏覽器或者不同主機發送來的請求的對待都是一樣的。就是每個請求都是獨立的,並不關心這個邏輯關係。
在這一篇中的主要內容也就講完了,好像看起來比較短哦,哈哈。。。。。那麼在講一些細節上的內容吧。
現在大併發的伺服器linux中,主要在有執行緒,程序,select,poll,epoll的方式。這些方式在各個部落格上都是有的,所以我並不想在解釋一下,讀者可以自己查詢其中的不同之處。而本文開發的HTTP伺服器採用執行緒的方式進行。主要是當一個請求來到時,就建立一個執行緒來處理。採用的linux下POSIX標準pthtread執行緒。如果其他讀者可以採用其他的幾種方式來處理。或者自己寫個執行緒池來取代每次一個請求來建立一個執行緒。主要對其包裹在一個名稱空間為MultiThread的執行緒Thread類中,接著是一些程式碼段:
標頭檔案(include/thread.h):
1 /* 2 * include/thread.h 3 */ 4 5 #ifndef THREAD_H_ 6 #define THREAD_H_ 7 #include<pthread.h> 8 #include<iostream> 9 namespace MultiThread { 10 11 class Thread { 12 public: 13 Thread(); 14 ~Thread(); 15 static int create_thread(pthread_t &pid,void* (*pFunc)(void *),void *arg); 16 int stop_thread(); 17 18 }; 19 20 } /* namespace MultiThread */ 21 22 #endif /* THREAD_H_ */
cpp檔案(src/thread.cpp)
1 /** 2 * 3 * src/thread.cpp 4 **/ 5 #include "thread.h" 6 namespace MultiThread { 7 8 Thread::Thread() { 9 } 10 11 Thread::~Thread() { 12 } 13 14 int Thread::create_thread(pthread_t &pid,void* (*pFunc)(void *),void *arg) { 15 int ret=pthread_create(&pid,NULL,pFunc,arg); 16 if(ret==0) 17 std::cout<<"create_thread() ...succeed"<<std::endl; 18 else 19 std::cout<<"create_thread() ...failed"<<std::endl; 20 return ret; 21 } 22 23 int Thread::stop_thread() { 24 return 0; 25 } 26 27 } /* namespace MultiThread */
看到現在,大家一定發現stop_thread()為空,應為我到現在還沒用這個函式。並且到現在只用到create_thread函式,之後如果用到,接著在之後的文章中提出吧。
如果大家對HTTP伺服器感興趣的話,接著看《Http伺服器實現檔案上傳與下載(三)》和我學習HTTP伺服器編寫吧。