成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

帶你手擼一個http服務器(帶源碼)

2021-02-01    分類: 網(wǎng)站建設

作為一個程序猿,對造輪子這事情可以說是情有獨鐘,幾乎

  • 精通JAVA,Python,熟練掌握C++
  • 精通Redis,Memcached,Mysql
  • 精通Nginx配置,模塊開發(fā)
  • 精通Kafka,ActiveMQ 等消息隊列
  • 精通常用數(shù)據(jù)結構和算法
  • 精通網(wǎng)絡編程,多線程編程技術,高性能服務器技術
  • 精通tcp/ip協(xié)議棧,熟悉內(nèi)核網(wǎng)絡子系統(tǒng)代碼
  • 精通nginx代碼及模塊開發(fā)
    • 上面每一條都涉及好多輪子,每一個都是精通,如果真能做到。那這個人可以說是碼農(nóng)中的戰(zhàn)斗機。

      那我們現(xiàn)在目標就是去做這個戰(zhàn)斗機。而這個方法,就是自己去造輪子,造的目的不是為了在項目中使用自己造的輪子,而是為了去了解輪子的構造,然后自己動手去體會造輪子的過程。


    • 抗在最前面的:LVS,F(xiàn)5,HAProxy這類負載均衡
    • 接下來有Nginx,Apache,Lighttpd這類Http服務
    • http服務后則是各種容器,部署著我們的業(yè)務邏輯
    • 存儲這邊有Redis,Memcached這一類KV存儲器和緩存系統(tǒng)
    • 如果是多機部署,肯定還有Kafka,ActiveMQ這種負責解耦的消息隊列
    • 為了實現(xiàn)集群通信,肯定少不了Thrift這種RPC框架和Protobuf這種序列化技術
    • 再高端點,到了分布式領域了,就是更多的輪子了。。zookeeper、raft等等
    • 還有大數(shù)據(jù)系列hadoop。spark。。。。。
      • 本文主要講http協(xié)議。

        正文分割線


        我們都知道http是基于tcp之上的,那我們現(xiàn)在就自己基于tcp來實現(xiàn)一個最小的http服務,功能非常簡單:

        • 返回輸入?yún)?shù)

        先來看請求格式:


        http的報文大概分為3部分:

        • 請求行
        • 首部
        • 正文部分

        此處請求行是格式是固定的,

        先寫代碼來看看的:


        可以看到我們讀取的到數(shù)據(jù)是如上,我們可以看到格式上是符合的。

        Ps:上面這個代碼有個小問題,因為tcp連接是字節(jié)流的,我們通過readAll方法從連接中讀取數(shù)據(jù)的是,只要瀏覽器上不主動斷開,會一直阻塞在readaALL上。。。

        上面我們將收到的數(shù)據(jù)稍微整理下

        • 請求行
        • POST / HPPP/1.1
        • 格式:方法 space URL space 版本 cr lf
        • 首部
        • Host: 127.0.0.1:8080
        • Content-length: 0
        • 格式:首部字段名 space 字段值 cr lf
        • 正文部分
        • 此處為空

        上面首部中Content-length: 0可以說是非常關鍵,他告訴了我們應該要在兩個 后繼續(xù)讀取多少字節(jié)。

        下面我們開始來寫解析代碼,先是解析文件頭


        然后我們再解析首部


        解析完后,我們在寫返回值,返回報文的格式放下:


        下面是返回值的代碼:


        完整的例子可以看GitHub上代碼,歡迎star

        https://github.com/zhuanxuhit/go-in-practice/tree/master/wheel/http/v1

        我們有了第一版http輪子后,我們能和前面介紹的輪子系列:rpc聯(lián)系起來,在rpc系列中,我們講了設計通信協(xié)議來傳遞消息,此處http是通過頭部的url+method的方法來表示我要調(diào)用服務端哪個方法,然后分割符是使用 ,連續(xù)兩個 表示后續(xù)是消息體,為了高速我們消息體的大小和格式,在header中必須指明content-type和content-length,這些都是在我們在實現(xiàn)http協(xié)議的時候遵循的。

        那現(xiàn)在寫完最初版代碼,我們回過頭總結下我們之前做的rpc輪子,數(shù)據(jù)編碼采用了protobuf,然后基于tcp自己定義了一套消息協(xié)議,其實做的事情跟http/1.1是一樣的,我們完全可以在http通信的時候,將content-type設置為protobuf,然后通信雙方雙方能夠編解碼即可。

        在實現(xiàn)過程中,我們發(fā)現(xiàn)如果用http1.1作為通信協(xié)議,有什么問題呢?

        1. 每次傳輸都要完整的http頭,浪費帶寬
        2. 每次一個http請求,一個request,response都要獨占一條tcp連接,不然不知道response對應哪個request,影響實時性和并發(fā)性

        那上面這兩點都是要解決的問題,在http2.0中都有相應的方案

        1. 針對每次都需要傳輸http頭,通信雙方建立索引,后續(xù)傳輸只用索引
        2. 針對連接占用,一條連接只能同時有一個請求-響應,http2.0啟動了多路復用,即允許一個連接同時發(fā)起多個請求

        那怎么能做到一個連接同時發(fā)起多個請求呢?通信雙方就必須對每個請求進行編碼,這樣不同的響應就能和請求對應上了。

        具體可以看兩張圖:


        HTTP 2.0 其實是將三個請求變成三個流,將數(shù)據(jù)分成幀,亂序發(fā)送到一個tcp連接中


        通過stream對不同請求進行區(qū)分,然后在將一個消息拆分為多個幀進行發(fā)送。

        那http2.0后,還能不能更快了呢?于是就有了QUIC協(xié)議,這個協(xié)議肯定是為了解決http2.0的某些問題的。

        1. 自定義連接機制:tcp連接三次握手慢,由于在移動端,由于網(wǎng)絡從wifi到移動網(wǎng)絡切換時,必定會導致連接斷開重連,再次需要3次握手,那我們就自定義連接機制,原先tcp一條連接是由4元素組成:分別是源 IP、源端口、目的 IP、目的端口,現(xiàn)在以一個64位隨機數(shù)來作為連接標志,斷開了也沒事,重新建立連接不需要3次握手了。
        2. 自定義重傳機制:tcp是可靠連接,當前面的數(shù)據(jù)編號沒有收到的時候,后面的數(shù)據(jù)即使收到了,也不會得到確認,這就必須要重傳

        重傳有個測不準問題,左邊是1.1,我們發(fā)現(xiàn)重發(fā)100編號的時候,如果后續(xù)收到應答101,我們不知道這個是針對第一次100的應答還是第二次重傳100的應答,http2.0則定義了每次發(fā)送數(shù)據(jù),編號都需要增加,然后通過offset來標明數(shù)據(jù)的前后續(xù)關系。

        1. 無阻塞多路復用:因為tcp是面向字節(jié)流的可靠連接,所以數(shù)據(jù)之間是有依賴的,因此為了減少依賴,讓不同流之間真的能夠獨立,可以采用udp
        2. 自定義流量控制:tcp的流量控制是通過滑動窗口協(xié)議,udp也是滑動窗口,而且是每個stream都有自己的窗口。

        總結

        首先本文基于tcp自己實現(xiàn)了http1.1的協(xié)議,實現(xiàn)中發(fā)現(xiàn)這個通信協(xié)議和我們之前輪子系列文章rpc都是消息協(xié)議,只是對消息體的編碼格式不同而已。

        接著我們在自己寫的過程中發(fā)現(xiàn)了http1.1的種種問題,針對這些問題有了http2.0,繼而又有了QUIC。

        本文名稱:帶你手擼一個http服務器(帶源碼)
        網(wǎng)站路徑:http://jinyejixie.com/news/98659.html

        成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供企業(yè)建站移動網(wǎng)站建設、App開發(fā)網(wǎng)站收錄、搜索引擎優(yōu)化、品牌網(wǎng)站制作

        廣告

        聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

        小程序開發(fā)
        永川市| 喀什市| 湄潭县| 正宁县| 海城市| 扶余县| 九台市| 桦川县| 霍州市| 太白县| 界首市| 康定县| 牙克石市| 石柱| 翁源县| 建平县| 衡阳市| 彭山县| 沙雅县| 永安市| 乐平市| 新田县| 新田县| 新乡县| 砀山县| 武平县| 墨江| 新巴尔虎右旗| 虹口区| 承德市| 宜君县| 新乡县| 枣强县| 贡嘎县| 苏尼特左旗| 长寿区| 兴国县| 墨脱县| 晋城| 郴州市| 西安市|