編寫簡單多執行緒web伺服器
刺蝟@http://blog.csdn.net/littlehedgehog
下面的原理解釋參照《乙個多執行緒web伺服器例項(c,linux,詳細的web伺服器原理)》 一文:
原理:在瀏覽器中輸入乙個**,回車之後,瀏覽器會向相應主機的相應埠傳送一段報文,如果是http協議的(如平常看到的網頁的傳輸協議),就會傳送http請求報文。下面是乙個報文的例子:
我們在伺服器端把收到的資料列印出來,可以看到瀏覽器發過來的就是這個東西。當然,也可以用ethereal等抓包工具來抓獲這些報文。關於報文裡寫的是什麼意思,網上有很多資料的,google一下就有了。我們只看第一行。
get表示是要從伺服器獲取檔案,/index.html是檔案的路 徑,這個路徑是相對於伺服器端程式所在資料夾的路徑。如我的伺服器端程式放在/home/mio/program/webserver1707/裡面,那 這個index.html在伺服器上的絕對路徑就是/home/mio/program/webserver1707/index.html。如果報文裡 是get /admin/login.html http/1.1的話,那麼login.html檔案在伺服器端的路徑是/home/mio/program/webserver1707/admin /login.html.http/1.1表示的是http協議的版本是1.1.
伺服器端程式執行後,一直監聽12345端品(0-1023的埠由 iana統一分配和控制的,不要用,最好選大一些的埠號。我原來用了個1234,用不了,還是選大一點好,可以用5460之類的啊~:) ),當監聽到客戶端發來的請求後,就與客戶端建立鏈結,接收客戶端發過來的請求報文。我們如果把這些報文打出來,就可以看到就是與上面請求報文類似的東西 了。
下面我們要根據所接受的到的請求報文(get /index.html http/1.1) 來決定放給客戶端(即瀏覽器)什麼東西。這裡我們看到瀏覽器要的是index.html這樣乙個html文字,我們就在相應路徑(/home/mio /program/webserver1707/index.html)找到這個檔案,不過不要急著發給客戶端,我們要先告訴客戶端,發過去的是乙個 html檔案,讓瀏覽器做好相應的準備。怎麼讓瀏覽器知道呢?我們還是用報文,這個報文叫響應報文。報文由狀態行、首部行、實體主體三部分組成。狀態行只 有一行,它和首部行、首部行的每行之間是沒有空行的,但是首部行與實體主體之間有乙個空行,表明從這個空行開始,就是你瀏覽器要的資料了。下面是乙個用 ethereal抓到的響應報文:
[email protected]| 個性化主頁https://www.google.com/accounts/manageaccount">我的帳戶 | http://www.google.com/accounts/logout?continue=http://www.google.com/intl/zh-cn/"> 退出
..........
第乙個空行上面的就是「說明」了,下面是html**。有了說明,瀏 覽器就知道這是什麼了,拿到這段資料後,就把這些html標籤解釋成各種各樣的元素,在瀏覽器上有序地顯示出來。瀏覽器還蠻聰明的,當看到
這樣,伺服器端就找到這個.jpg影象,加上"說明"之後發給瀏覽器,瀏覽器收到後就顯示在對應的位置上。遇到包含css、js...的標籤也一樣。
如此重複,乙個完整的web就會呈現在我們眼前了。
這裡是伺服器原始碼,本來打算可以傳完整http網頁的,包括。不過傳輸一直有問題。暫時放一放了。
#include
#include
#include
#include
#include
#include
#include
#define hostlen 256
#define portnum 12345
//#define debug
int make_server_socket_q(int,int);
void error(char *err)
int make_server_socket(int port) //num for listen
int make_server_socket_q(int port,int backlog)
/* 允許接入*/
if(listen(sock_id,3))
error("listen failed");
return sock_id;
}/* 測試是否存在 */
int check_exist(char *filename)
/* 檢測檔案型別 */
char * file_type(char *filename)
/* 報文 頭部 */
void do_head(int sock_fd,char *type)
/* 404 檔案沒找到 */
void do_nofile(char *filename,int sock_fd)
/* 處理其它命令 */
void do_unkown(int sock_fd)
/* 核心處理 從檔案中讀取 然後寫入socket */
content="text/plain"; //預設處理
sock_fp=fdopen(sock_fd,"w");
file_fp=fopen(arg,"rb");
if(file_fp!=null&&sock_fp!=null)
}/* request處理 */
int process_rq(char *request,int sock_fd)
/* 執行緒主函式 */
void thread_routine(void *fd)
int main(int argc,char *argv)
port=argc==1?portnum:atoi(argv[1]); //注意這裡如果只有乙個引數,即是設定預設埠
if((sock_id=make_server_socket(port))==-1)
return -1;
printf("now listen to the port #%d/n",port);
fflush(stdout);
while(1)
return 0;
}
python實現多執行緒web伺服器
自定義執行緒函式 def server tcpclisock,addr bufsize 1024 print waiting for the connection addr data tcpclisock.recv bufsize decode filename data.split 1 filen...
web伺服器 簡單web伺服器實現
三次握手 一般情況下是瀏覽器先傳送請求資料,c s ack 應答 三次握手成功後,才開始進行通訊資料的收發。四次揮手 一般情況下是客戶端先關閉,給瀏覽器傳送關閉資訊。如果瀏覽器傳送了關閉資訊,但是伺服器沒有回過去,較慢 那麼瀏覽器一直發是不是就會有問題?所以會等待 2msl的時間。一般為2 5分鐘。...
多執行緒伺服器
posix執行緒庫 a 與執行緒有關的函式都構成了乙個完整的系列,絕大多數函式的名字都是以 pthread 打頭的。b 要使用這些庫函式,要引入標頭檔案。c 鏈結這些執行緒庫函式時要使用編譯命令的 lpthread 選項。int pthread create pthread t thread,con...