青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

loop_in_codes

低調做技術__歡迎移步我的獨立博客 codemaro.com 微博 kevinlynx

實現自己的http server

Write your own http server

author : Kevin Lynx

Why write your own?

    看這個問題的人證明你知道什么是http server,世界上有很多各種規模的http server,為什么要自己實現一個?其實沒什么
理由。我自己問自己,感覺就是在自己娛樂自己,或者說只是練習下網絡編程,或者是因為某日我看到某個庫宣稱自己附帶一個小
型的http server時,我不知道是什么東西,于是就想自己去實現一個。

What's httpd ?

    httpd就是http daemon,這個是類unix系統上的名稱,也就是http server。httpd遵循HTTP協議,響應HTTP客戶端的request,
然后返回response。
    那么,什么是HTTP協議?最簡單的例子,就是你的瀏覽器與網頁服務器之間使用的應用層協議。雖然官方文檔說HTTP協議可以
建立在任何可靠傳輸的協議之上,但是就我們所見到的,HTTP還是建立在TCP之上的。
    httpd最簡單的response是返回靜態的HTML頁面。在這里我們的目標也只是一個響應靜態網頁的httpd而已(也許你愿意加入CGI
特性)。

More details about HTTP protocol

    在這里有必要講解HTTP協議的更多細節,因為我們的httpd就是要去解析這個協議。
    關于HTTP協議的詳細文檔,可以參看rfc2616。但事實上對于實現一個簡單的響應靜態網頁的httpd來說,完全沒必要讀這么一
分冗長的文檔。在這里我推薦<HTTP Made Really Easy>,以下內容基本取自于本文檔。

- HTTP協議結構
  HTTP協議無論是請求報文(request message)還是回應報文(response message)都分為四部分:
  * 報文頭 (initial line )
  * 0個或多個header line
  * 空行(作為header lines的結束)
  * 可選body
  HTTP協議是基于行的協議,每一行以\r\n作為分隔符。報文頭通常表明報文的類型(例如請求類型),報文頭只占一行;header line
  附帶一些特殊信息,每一個header line占一行,其格式為name:value,即以分號作為分隔;空行也就是一個\r\n;可選body通常
  包含數據,例如服務器返回的某個靜態HTML文件的內容。舉個例子,以下是一個很常見的請求報文,你可以截獲瀏覽器發送的數據
  包而獲得:

    1  GET /index.html HTTP/1.1
    2  Accept-Language: zh-cn
    3  Accept-Encoding: gzip, deflate
    4  User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; MAXTHON 2.0)
    5  Host: localhost
    6  Connection: Keep-Alive
    7
  我為每一行都添加了行號,第1行就是initial line,2-6行是header lines,7行是一個header line的結束符,沒有顯示出來。
  以下是一個回應報文:
    1  HTTP/1.1 200 OK
    2  Server: klhttpd/0.1.0
    3  Content-Type: text/html
    4  Content-Length: 67
    5
    6  <head><head><title>index.html</title></head><body>index.html</body>
  第6行就是可選的body,這里是index.html這個文件的內容。

- HTTP request method
  因為我們做的事服務器端,所以我們重點對請求報文做說明。首先看initial line,該行包含幾個字段,每個字段用空格分開,例
  如以上的GET /index.html HTTP/1.1就可以分為三部分:GET、/index.html、HTTP/1.1。其中第一個字段GET就是所謂的request
  method。它表明請求類型,HTTP有很多method,例如:GET、POST、HEAD等。

  就我們的目標而言,我們只需要實現對GET和HEAD做響應即可。

  GET是最普遍的method,表示請求一個資源。什么是資源?諸如HTML網頁、圖片、聲音文件等都是資源。順便提一句,HTTP協議
  中為每一個資源設置一個唯一的標識符,就是所謂的URI(更寬泛的URL)。
  HEAD與GET一樣,不過它不請求資源內容,而是請求資源信息,例如文件長度等信息。

- More detail
  繼續說說initial line后面的內容:
  對應于GET和HEAD兩個method,緊接著的字段就是資源名,其實從這里可以看出,也就是文件名(相對于你服務器的資源目錄),例
  如這里的/index.html;最后一個字段表明HTTP協議版本號。目前我們只需要支持HTTP1.1和1.0,沒有多大的技術差別。

  然后是header line。我們并不需要關注每一個header line。我只羅列有用的header line :
  - Host : 對于HTTP1.1而言,請求報文中必須包含此header,如果沒有包含,服務器需要返回bad request錯誤信息。
  - Date : 用于回應報文,用于客戶端緩存數據用。
  - Content-Type : 用于回應報文,表示回應資源的文件類型,以MIME形式給出。什么是MIME?它們都有自己的格式,例如:
    text/html, image/jpg, image/gif等。
  - Content-Length : 用于回應報文,表示回應資源的文件長度。

body域很簡單,你只需要將一個文件全部讀入內存,然后附加到回應報文段后發送即可,即使是二進制數據。

- 回應報文
  之前提到的一個回應報文例子很典型,我們以其為例講解。首先是initial line,第一個字段表明HTTP協議版本,可以直接以請求
  報文為準(即請求報文版本是多少這里就是多少);第二個字段是一個status code,也就是回應狀態,相當于請求結果,請求結果
  被HTTP官方事先定義,例如200表示成功、404表示資源不存在等;最后一個字段為status code的可讀字符串,你隨便給吧。

  回應報文中最好跟上Content-Type、Content-Length等header。

具體實現
    正式寫代碼之前我希望你能明白HTTP協議的這種請求/回應模式,即客戶端發出一個請求,然后服務器端回應該請求。然后繼續
這個過程(HTTP1.1是長連接模式,而HTTP1.0是短連接,當服務器端返回第一個請求時,連接就斷開了)。
    這里,我們無論客戶端,例如瀏覽器,發出什么樣的請求,請求什么資源,我們都回應相同的數據:

               

/* 阻塞地接受一個客戶端連接 */
        SOCKET con 
= accept( s, 00 ); 
        
/* recv request */
        
char request[1024= 0 };
        ret 
= recv( con, request, sizeof( request ), 0 );
        printf( request );
        
/* whatever we recv, we send 200 response */
        
{
            
char content[] = "<head><head><title>index.html</title></head><body>index.html</body>";
            
char response[512];
            sprintf( response, 
"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: %d\r\n\r\n%s", strlen( content ), content );
            ret 
= send( con, response, strlen( response ), 0 );
        }

        closesocket( con ); 

 

    程序以最簡單的阻塞模式運行,我們可以將重點放在協議的分析上。運行程序,在瀏覽器里輸入http://localhost:8080/index.html
,然后就可以看到瀏覽器正常顯示content中描述的HTML文件。假設程序在8080端口監聽。

   現在你基本上明白了整個工作過程,我們可以把代碼寫得更全面一點,例如根據GET的URI來載入對應的文件然后回應給客戶端。
其實這個很簡單,只需要從initial line里解析出(很一般的字符串解析)URI字段,然后載入對應的文件即可。例如以下函數:

void http_response( SOCKET con, const char *request )
{
    
/* get the method */
    
char *token = strtok( request, " " );
    
char *uri = strtok( 0" " );
    
char file[64];
    sprintf( file, 
".%s", uri ); 

    
{
        
/* load the file content */
        FILE 
*fp = fopen( file, "rb" );
        
if( fp == 0 )
        
{
            
/* response 404 status code */
            
char response[] = "HTTP/1.1 404 NOT FOUND\r\n\r\n";
            send( con, response, strlen( response ), 
0 );
        }

        
else
        
{
            
/* response the resource */
            
/* first, load the file */
            
int file_size ;
            
char *content;
            
char response[1024];
            fseek( fp, 
0, SEEK_END );
            file_size 
= ftell( fp );
            fseek( fp, 
0, SEEK_SET );
            content 
= (char*)malloc( file_size + 1 );
            fread( content, file_size, 
1, fp );
            content[file_size] 
= 0

            sprintf( response, 
"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: %d\r\n\r\n%s", file_size, content );
            send( con, response, strlen( response ), 
0 );
            free( content );
        }

    }

}
 



其他

    要將這個簡易的httpd做完善,我們還需要注意很多細節。包括:對不支持的method返回501錯誤;對于HTTP1.1要求有Host這個
header;為了支持客戶端cache,需要添加Date header;支持HEAD請求等。

    相關下載中我提供了一個完整的httpd library,純C的代碼,在其上加上一層資源載入即可實現一個簡單的httpd。在這里我將
對代碼做簡要的說明:
    evbuffer.h/buffer.c : 取自libevent的buffer,用于緩存數據;
    klhttp-internal.h/klhttp-internal.c :主要用于處理/解析HTTP請求,以及創建回應報文;
    klhttp-netbase.h/klhttp-netbase.c :對socket api的一個簡要封裝,使用select模型;
    klhttp.h/klhttp.c :庫的最上層,應用層主要與該層交互,這一層主要集合internal和netbase。
    test_klhttp.c :一個測試例子。

相關下載:
    klhttpd
    文中相關代碼

參考資料:

http://www.w3.org/Protocols/rfc2616/rfc2616.html
http://jmarshall.com/easy/http/
http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

posted on 2008-07-30 16:14 Kevin Lynx 閱讀(29797) 評論(21)  編輯 收藏 引用 所屬分類: network

評論

# re: 實現自己的http server 2008-07-30 23:52 zx

其實對于Server來說,最難的部分是如何能盡快更多的響應Client的請求,這里多線程似乎作用不大,最好的方式是用Async模式運行,而且還要用到IO的overlapped……  回復  更多評論   

# re: 實現自己的http server 2008-07-31 00:08 x-matrix

@zx
這只是個練習而已,何必苛求。
  回復  更多評論   

# re: 實現自己的http server 2008-07-31 08:56 Kevin Lynx

@zx
高并發數不見得要使用async(不明白你所謂的Async模式是什么?我假設是異步IO),也不見得要使用Overlapped IO (我也不明白你說的"IO的overlapped",我假設是windows下的Overlapped IO),一個event-driven的網路模型就很不錯了。

@x-matrix
本文的重點在于對HTTP協議的解析,而不是開發高并發網絡框架。:)  回復  更多評論   

# re: 實現自己的http server 2008-07-31 16:15 土仔

很贊同你的這種做法(精神?),其實做出一個東西有時只是為了能熟悉它的一些特性和滿足自己的娛樂精神。  回復  更多評論   

# re: 實現自己的http server 2008-08-01 14:57 Strive

當然,看過 http://home.xxsyzx.com/home/ 這個的話,才真正能滿足自己的娛樂精神。。  我一向都是報著做著好玩來玩這種程序。  回復  更多評論   

# re: 實現自己的http server 2008-08-01 16:08 Kevin Lynx

@Strive
很巧, 我恰好看過這個網站,感覺是個少年天才的主頁。之前搜索QQ協議,發現的。還下了他寫的QQ客戶端,不過有問題,我登陸Q后,就被T了。  回復  更多評論   

# re: 實現自己的http server 2008-08-04 19:37 sinodragon21

http://home.xxsyzx.com/home/ 看了Strive和樓主提到的這個URL,感覺真的很不可思議!太有才了~!Unbelievable!  回復  更多評論   

# re: 實現自己的http server 2008-08-04 20:19 矩陣操作

HTTP協議最麻煩是cookie那部分,以前寫過,感覺好惡。。。

btw,也去看了這個http://home.xxsyzx.com/home/ ,靠,NB,這個webqq確實搞得不錯,我在上面聊了,很正常啊,沒有被T。回頭研究研究。  回復  更多評論   

# re: 實現自己的http server 2008-08-04 20:27 francis

我很少相信天才,這一次不得不信。。。 而且是少年天才。。。  回復  更多評論   

# re: 實現自己的http server 2008-08-04 20:53 矩陣操作

看了代碼,結構設計和編寫質量還可以,居然達到鄙人參加工作8年才達到的實力。。。。。代碼里面幾乎沒有注釋。。。

現在的年輕人,太厲害了。確實是個天才  回復  更多評論   

# re: 實現自己的http server 2008-09-04 11:12 dikatour

我覺得最后一段代碼有些問題。
因為讀出的文件內容都是二進制讀出,文件內容可能包含'\0', 因此sprinf會丟棄'\0'后面的內容。  回復  更多評論   

# re: 實現自己的http server 2008-09-04 13:53 Kevin Lynx

@dikatour
這個測試例子確實可能出現這樣的問題。但是在klhttpd中則不會存在,response的內容都交給應用層去做。

  回復  更多評論   

# re: 實現自己的http server 2009-06-01 10:20 zwp

我也寫過類似的程序,功能比lz這個稍微豐富一些,呵呵:)
http://sites.google.com/site/cxtools/socket-1/MiniWebServ.rar  回復  更多評論   

# re: 實現自己的http server[未登錄] 2010-02-04 19:12 tess

我覺得這個程序有點問題,用瀏覽器連上服務器以后,程序就進入死循環了,一直進行寫操作,而根本沒數據可寫。最近在學網絡開發,感謝樓主提供怎么好的例子:)。  回復  更多評論   

# re: 實現自己的http server 2010-10-25 11:56 xx

Just Test  回復  更多評論   

# re: 實現自己的http server 2010-11-13 21:18 xx

@土仔
想當初Linus也是剛剛買了太新機子,想試試386保護模式下編程而已,沒想到寫著寫著就成linux了。。。  回復  更多評論   

# re: 實現自己的http server[未登錄] 2011-10-16 23:13 cc

就這個。。。也好意思拿來顯擺。。。  回復  更多評論   

# re: 實現自己的http server 2013-07-29 22:29 yyy

我也寫了一個WEB服務器:
http://www.crsky.com/soft/37864.html  回復  更多評論   

# re: 實現自己的http server 2013-07-30 09:26 業汶

學會了寫WEB服務器的思路,謝謝樓主。  回復  更多評論   

# re: 實現自己的http server[未登錄] 2013-11-12 14:23 Fly

@yyy
你好!看了你寫的web服務器,挺不錯的。代碼能否發一份給我呢?謝謝!
346296192@qq.com  回復  更多評論   

# re: 實現自己的http server 2014-03-20 16:58 io哦i

dfsdfs  回復  更多評論   

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美一区三区三区高中清蜜桃| 久久精品中文字幕免费mv| 欧美 日韩 国产在线| 亚洲黄一区二区| 亚洲激情在线观看| 欧美成人综合在线| 亚洲免费婷婷| 久久精品日韩| 在线视频日韩精品| 欧美亚洲日本国产| 91久久精品日日躁夜夜躁欧美 | 欧美在线播放一区二区| 久久国产精品一区二区三区| 亚洲欧洲精品一区二区三区不卡 | 亚洲免费在线看| 国内精品久久久久久久影视麻豆 | 免费欧美高清视频| 亚洲欧美怡红院| 久久久视频精品| 日韩视频免费观看高清完整版| 亚洲少妇中出一区| 一区在线播放| 亚洲私人影吧| 亚洲人线精品午夜| 欧美一区二区在线免费观看| 亚洲人久久久| 亚洲天堂网在线观看| 亚洲国产一区在线| 亚洲欧美影音先锋| 一区二区91| 久久综合中文色婷婷| 性欧美8khd高清极品| 欧美国产日本韩| 久久久国产精品一区| 欧美三级在线| 亚洲国产一区二区三区在线播| 国产欧美日韩在线观看| 日韩手机在线导航| 91久久综合| 久久久爽爽爽美女图片| 欧美日韩国产成人精品| 欧美va天堂在线| 国产日韩精品一区观看 | 久久xxxx精品视频| 欧美日韩在线一区二区三区| 免费亚洲一区| 好吊日精品视频| 亚洲字幕一区二区| 亚洲欧美成人网| 欧美日韩另类综合| 亚洲黄色大片| 亚洲欧洲一区二区在线播放| 久久久蜜桃精品| 久久婷婷久久| 国产最新精品精品你懂的| 亚洲欧美日韩精品综合在线观看| 亚洲性av在线| 欧美视频免费在线| 99视频有精品| 亚洲一区二区三区乱码aⅴ| 欧美日韩激情网| 亚洲免费观看视频| 制服丝袜亚洲播放| 国产精品极品美女粉嫩高清在线 | 久久精品官网| 国产亚洲永久域名| 久久久久国产一区二区三区四区 | 亚洲九九精品| 亚洲性夜色噜噜噜7777| 欧美性做爰毛片| 亚洲一区二区三区中文字幕在线| 亚洲欧美日韩精品在线| 国产精品视频导航| 久久疯狂做爰流白浆xx| 久久视频在线视频| 最新成人av网站| 欧美成人一区在线| 9久re热视频在线精品| 亚洲免费在线观看视频| 国产精品夜色7777狼人 | 亚洲网站在线看| 久久精品国产久精国产思思| 狠狠色丁香婷婷综合久久片| 久久人人爽人人爽爽久久| 欧美第十八页| 亚洲专区一区| 国产视频一区在线| 免费观看不卡av| 夜夜爽99久久国产综合精品女不卡 | 久久久久久久网| 亚洲精品乱码久久久久久蜜桃麻豆| 一区二区三区久久| 国产午夜久久| 欧美伦理91| 久久精品亚洲一区二区| 亚洲高清不卡在线| 欧美一区二区在线观看| 91久久国产综合久久蜜月精品| 欧美午夜久久久| 久久久亚洲成人| 制服丝袜激情欧洲亚洲| 亚洲国语精品自产拍在线观看| 欧美日韩不卡| 久久精品中文字幕免费mv| 99国产精品国产精品久久| 久久精品中文字幕一区二区三区| 在线看片成人| 国产嫩草影院久久久久| 欧美成人免费在线观看| 香蕉乱码成人久久天堂爱免费| 欧美激情网站在线观看| 欧美一二三视频| 一区二区三区不卡视频在线观看 | 国产一区视频在线看| 欧美成人在线免费观看| 久久精品一区二区国产| 在线亚洲一区观看| 欧美电影免费观看网站| 欧美一区二区日韩| 亚洲小说欧美另类社区| 91久久中文| 亚洲国产综合视频在线观看| 国产亚洲va综合人人澡精品| 欧美视频一区二区三区…| 免费一区视频| 久久免费视频网站| 亚洲手机成人高清视频| 亚洲日本免费电影| 亚洲国产乱码最新视频| 免费在线视频一区| 另类激情亚洲| 久久综合伊人77777麻豆| 久久riav二区三区| 久久国产精品色婷婷| 午夜精品短视频| 亚洲一二区在线| 在线一区二区三区四区五区| 亚洲精品一区在线| 99精品国产99久久久久久福利| 91久久嫩草影院一区二区| 亚洲激情视频网站| 亚洲精品在线视频| 一本色道久久综合亚洲精品高清| 亚洲精品视频在线播放| 亚洲精品久久久久| 日韩亚洲视频| 亚洲视频一区二区免费在线观看| 亚洲视频免费看| 亚洲欧美在线一区二区| 欧美一区二区三区免费观看视频| 香蕉视频成人在线观看| 欧美一区二区精品在线| 欧美综合77777色婷婷| 欧美一区二区高清在线观看| 欧美一区91| 久久久精品一区| 久久综合给合久久狠狠狠97色69| 久久免费观看视频| 免费一级欧美片在线观看| 欧美国产极速在线| 亚洲肉体裸体xxxx137| 亚洲性感美女99在线| 欧美在线一二三四区| 狂野欧美激情性xxxx| 欧美日韩成人网| 国产精品色在线| 狠狠入ady亚洲精品| 91久久精品日日躁夜夜躁国产| 一区二区三区日韩| 久久久国产精品一区二区三区| 欧美波霸影院| 亚洲天堂网在线观看| 久久久女女女女999久久| 欧美激情黄色片| 欧美日韩国产精品一区二区亚洲 | 欧美不卡视频一区| 国产精品视频久久| 久久影院亚洲| 国产精品超碰97尤物18| 在线日韩电影| 亚洲一区高清| 欧美暴力喷水在线| 亚洲综合色激情五月| 欧美国产日韩精品| 国产亚洲亚洲| 亚洲影视在线播放| 亚洲国产黄色| 久久gogo国模裸体人体| 欧美日韩亚洲一区三区 | 亚洲黄色在线看| 久久久夜夜夜| 中文精品视频一区二区在线观看| 久久夜色精品国产亚洲aⅴ| 国产精品色网| 亚洲视频电影图片偷拍一区| 欧美国产欧美亚洲国产日韩mv天天看完整| 亚洲女女女同性video| 欧美成人精品激情在线观看| 国内不卡一区二区三区| 欧美在线播放视频|