中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Go語言網絡編程與Http源碼分析

發布時間:2023-03-28 16:20:37 來源:億速云 閱讀:104 作者:iii 欄目:開發技術

這篇文章主要介紹“Go語言網絡編程與Http源碼分析”,在日常操作中,相信很多人在Go語言網絡編程與Http源碼分析問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Go語言網絡編程與Http源碼分析”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

    網絡分層

    這塊知識屬于計算機網絡,可以直接去看書。

    我們這里直接上圖:

    Go語言網絡編程與Http源碼分析

    我們最常講的是五層協議,最重要的是運輸層和應用層,這兩層是大多數情況下,工程師可以在代碼中可以直接干預的模塊,我們大多數的網絡編程調優,就是在調這些協議的一些參數和細節。這兩層的情況:

    • 運輸層協議:TCP和UDP。

    • 應用層協議:Http,SMTP,FTP,WebSocket等等,這些協議需要使用運輸層協議作為依托。

    引申,需要注意TCP和UDP的區別,和他們具體的使用場景。

    順便提一句,網絡分層本質上也是我們反復提過得加一層的思想,也是高內聚低耦合的一種具體的實現。

    進程間通信(IPC)

    這塊知識屬于操作系統,注意不是Linux操作系統,還牽扯一點計算機組成原理的知識。

    IPC 是 Inter-Process Communication 的縮寫,可以被翻譯為進程間通信。主要方法有: 系統信號(signal)、管道(pipe)、套接字 (socket)、文件鎖(file lock)、消息隊列(message queue)、信號量(semaphore)等。最常用的是系統信號,套接字,還有一個叫共享內存的,能實現,但不提倡。Go底層的os包里也包含著這些常用的方法。

    這里需要再引申下,操作系統中進程和線程是什么,協程又是什么。進程間是如何通信的,線程間又是如何通信的。

    我們單獨把socket拎出來說,因為在眾多方案中,就屬它比較通用,比較靈活:使用socket可以跨機器進行通訊。

    Socket

    實際上,現代操作系統的內核都會帶有socket相關的API,我們的代碼在運行時,只需要調用操作系統提供的接口,就可以輕松建立網絡連接,這也是我們之前講過的面向接口編程的具體場景之一。

    我們這里直接講Go語言中的Socket。在GO語言中有一個叫做syscall的包,里面有對應的一整套的socket的方法,并且這些方法是做過跨平臺處理的,我們最常用的Http包里的許多建立連接,接收內容的方法都直接或者間接的用了syscall包。

    總而言之,我們常用的Http包在建立鏈接時需要使用到socket,socket建立連接時需要具體的傳輸層協議。

    Http

    基礎知識

    HTTP屬于應用層協議,也就是最頂層協議。目前他有三個版本:

    • HTTP1.1 最常用的版本,使用TCP作為運輸層協議。

    • HTTP2 一個升級版本,用的不多。同樣使用TCP作為運輸層協議。

    • HTTP3 設計了一個新的傳輸層協議QUIC,可以選擇TCP或者UDP來傳輸數據。

    注意,HTTP協議誕生的年代相當久遠,它是一個無狀態的協議。

    一個HTTP的請求有兩部分組成:頭部header和主體body。

    //這是一個GET請求的頭部。
    :authority: api.bilibili.com
    :method: GET
    :path: /x/web-interface/bgroup/member/in?business=MGR&name=PCQoE%E4%BA%BA%E7%BE%A41&dimension=1
    :scheme: https
    accept: application/json, text/plain, */*
    accept-encoding: gzip, deflate, br
    accept-language: zh-CN,zh;q=0.9,sm;q=0.8,en;q=0.7
    cache-control: no-cache
    cookie: 
    origin: https://www.bilibili.com
    pragma: no-cache
    referer: https://www.bilibili.com/?utm_source=gold_browser_extension
    user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36

    頭部中有幾個特別的字段需要關注下。origin,referer, user-agent, accept。另外,還有幾個特別的字段:Content-Length,Connection。TCP協議本身是基于字節流的,它無法區分消息邊界,需要應用層協議自己來實現。

    可以詳細看下Response返回的頭部中都有哪些字段。另外,一些常見的字段我們經常在Postman中使用。

    客戶端

    在Go語言中啟動一個客戶端是相當簡單的一件事,Go為HTTP提供了大量的開箱即用的工具。

    url := "https://www.bilibili.com" //我們要請求的地址
    resp, err := http.Get(url) //get請求,經典返回:內容和一個ERR
    defer func() {
    	_ = resp.Body.Close()  //通常我們需要及時關閉掉返回內容。
    }()
    if err != nil {
    	fmt.Printf("請求錯誤: %v\n", err)
    }
    fmt.Printf("返回狀態:\n%s\n", resp.Status)

    但是,我們通常不會這樣直接調用。http.Get的底層調用的是http.Client,返回的是http.Response。通常情況下,我們會使用http.Client結合業務場景來構造一些請求:

    url := "https://www.bilibili.com"
    req, _ := http.NewRequest(http.MethodGet, url, nil) //req 是一個Request結構,它有大量的方法的熟悉 可以自定義。
    req.Form.Add("test", "1231")                        //構造一個表單提交
    req.Header.Set("Cookie", "123")                     //設置Cookie
    resp, err := http.DefaultClient.Do(req) //這里使用的依然是默認的DefaultClient
    if err != nil {
    	fmt.Printf("請求錯誤: %v\n", err)
    }
    defer func() {
    	_ = resp.Body.Close()
    }()
    fmt.Printf("返回狀態:\n%s\n", resp.Status)

    正常情況下,我們使用http.DefaultClient.Do,直接調用默認的http.Client就可以正常發起請求。在某些情況下,公司內部會封裝一個統一的http.Client,里面會集成一些公司內統一的調用標識,服務請求方,提供方,trace,機器編碼,統一的過期時間等配置信息。

    http.Client的結構非常簡單:

    type Client struct {
    	Transport RoundTripper //真正干活的結構體
    	CheckRedirect func(req *Request, via []*Request) error //一個重定向校驗方法,用的比較少
    	Jar CookieJar //Cookie包,我們常用的方法都在這個接口中
    	Timeout time.Duration //單次完整HTTP請求的超時時間,0代表沒有設置。
    }

    如果有時間,可以看下 DefaultTransport的源碼,通過簡單配置,進而理解Http與TCP的一些關鍵配置項的含義。

    最后,如果你愿意也可以自己造個輪子,但是我們決不提倡這種行為。

    conn, err := net.Dial("tcp", "bilibili.com:80")
    if err != nil {
    	fmt.Printf("connect err => %s\n", err.Error())
    }
    buf := bytes.Buffer{}
    buf.WriteString("GET / HTTP/1.1\r\n")
    buf.WriteString("Host: baidu.com\r\n")
    buf.WriteString("USer-Agent: Go-http-client/1.1\r\n")
    // 請求頭結束
    buf.WriteString("\r\n")
    // 請求body結束
    buf.WriteString("\r\n\r\n")
    _, _ = conn.Write(buf.Bytes())
    // 獲取響應信息
    resp, _ := io.ReadAll(conn)
    fmt.Printf("響應信息\n%q", resp)

    http.Client的底層是基于net.Dial實現的,net.Dial底層又調用了操作系統的Socket相關接口。

    可以嘗試實現一個Post方法。

    服務端

    Go語言搭建一個服務器非常簡單,只需要用到幾個方法:

    http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
    	_, _ = fmt.Fprintf(writer, "關注 香香編程喵喵喵,關注香香編程謝謝喵喵喵!")
    })
    panic(http.ListenAndServe(":8080", nil))

    http.HandleFunc用來注冊一個處理器。其內部會持有一個哈希,用來存儲路徑與處理器的映射關系。注意,這里和Gin框架就有區別了。

    http.ListenAndServe用來監聽一個端口上的TCP鏈接,并處理后續的請求。它的底層調用的是net.Listen,同樣也是基于Socket的方法,我們這里不做展開。

    到此,關于“Go語言網絡編程與Http源碼分析”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    麻栗坡县| 江川县| 桃江县| 乐平市| 科技| 光泽县| 兴城市| 岫岩| 察哈| 霸州市| 伊宁市| 姚安县| 淄博市| 绥中县| 鹤壁市| 正宁县| 永丰县| 揭东县| 宁强县| 呼图壁县| 长泰县| 南江县| 定西市| 南木林县| 白沙| 眉山市| 郸城县| 定南县| 兰坪| 资源县| 通州市| 专栏| 余庆县| 许昌县| 蛟河市| 曲松县| 三明市| 咸阳市| 新建县| 白水县| 洮南市|