欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Golang中基于HTTP協(xié)議的網(wǎng)絡服務

 更新時間:2023年04月13日 11:22:44   作者:鯤鵬飛九萬里  
HTTP協(xié)議是基于TCP/IP協(xié)議棧的,并且它也是一個面向普通文本的協(xié)議。這篇文章主要詳細介紹了Golang中基于HTTP協(xié)議的網(wǎng)絡服務,感興趣的小伙伴可以借鑒一下

一、HTTP協(xié)議的網(wǎng)絡服務

HTTP協(xié)議是基于TCP/IP協(xié)議棧的,并且它也是一個面向普通文本的協(xié)議。

只要搞清楚了HTTP請求的報文(報文的頭部(header)和主體(body))應該包含的內(nèi)容,使用任何一個文本編譯器,就餓可以編寫一個完整的HTTP請求報文。

在這種情況下,直接使用net.Dial函數(shù),就可以。

使用net/http代碼包中的程序?qū)嶓w,可以更便捷的訪問基于HTTP協(xié)議的網(wǎng)絡服務。其中最便捷的是使用http.Get函數(shù)。

1.1 使用http.Get函數(shù)訪問HTTP協(xié)議的網(wǎng)絡服務

package main

import (
	"fmt"
	"net/http"
)

func main() {
	url1 := "http://www.google.cn/"
	fmt.Printf("Send request to %q with method GET ... \n", url1)
	response1, err := http.Get(url1)
	if err != nil {
		fmt.Printf("request sending error: %v\n", err)
	}
	defer response1.Body.Close()
	line1 := response1.Proto + " " + response1.Status
	fmt.Printf("The first line of response: \n %s \n", line1)
}

http.Get函數(shù)會返回兩個結(jié)果值:

  • 第一個結(jié)果值的類型是*http.Response,它是網(wǎng)絡服務給我們傳回來的響應內(nèi)容的結(jié)構化表示。
  • 第二個結(jié)果值是error類型。它代表了在創(chuàng)建和發(fā)送HTTP請求,以及接受和解析HTTP響應的過程中可能發(fā)生的錯誤。

http.Get函數(shù)內(nèi)部會使用缺省的HTTP客戶端,并調(diào)用它的Get方法以完成功能。缺省客戶端類型是*http.Client,由公開變量DefaultClient代表。

1.2 使用缺省客戶端DefaultClient(類型為*http.Client )

package main

import (
	"fmt"
	"net/http"
)

func main() {
	url1 := "http://www.google.cn/"
	fmt.Printf("Send request to %q with method GET ... \n", url1)
	// response1, err := http.Get(url1)
	response1, err := http.DefaultClient.Get(url1)
	if err != nil {
		fmt.Printf("request sending error: %v\n", err)
	}
	defer response1.Body.Close()
	line1 := response1.Proto + " " + response1.Status
	fmt.Printf("The first line of response: \n %s \n", line1)
}

它的基本類型(http.Client)可以開箱即用。

1.3 使用http.Client訪問HTTP協(xié)議的網(wǎng)絡服務

package main

import (
	"fmt"
	"net/http"
)

func main() {
	url1 := "http://www.google.cn/"
	fmt.Printf("Send request to %q with method GET ... \n", url1)
	// response1, err := http.Get(url1)
	// response1, err := http.DefaultClient.Get(url1)
	var oneClient http.Client
	response1, err := oneClient.Get(url1)
	if err != nil {
		fmt.Printf("request sending error: %v\n", err)
	}
	defer response1.Body.Close()
	line1 := response1.Proto + " " + response1.Status
	fmt.Printf("The first line of response: \n %s \n", line1)
}

http.Client是一個結(jié)構體類型,并且它包含的字段是公開的。之所以該類型的零值仍然可以使用,是因為它的這些字段要么存在著響應的缺省值,要么其零值直接可以使用,且代表著特定的含義。

二、http.Client中的Transport字段

http.Client類型中的Transport字段代表著:向網(wǎng)絡服務發(fā)送HTTP請求,并從網(wǎng)絡服務接收HTTP響應的操作過程。

Transport字段的RoundTrip方法實現(xiàn)單次HTTP事務(或者說基于HTTP協(xié)議的單詞交互)需要的所有步驟。

 Transport 字段是http.RoundTrip接口類型,它有一個缺省值,這個缺省值的變量名為DefaultTransport。DefaultTransport的實際類型為*http.Transport,*http.Transport可以被復用,并且是線程安全的。

如果沒有顯式的為http.Client中的Transport字段賦值,這個Client就會直接使DefaultTransport。

 http.Client中的Timeout字段,代表前面所說的單詞HTTP事務的超時時間,它time.Duration類型,它的零值是可用的,用于表示沒有設置超時時間。

(1)http.Transport類型中的DialContext字段

http.Transport類型,在內(nèi)部使用一個net.Dialer類型的值,并且會把該值的Timeout字段的值,設定為30秒。

也就是說,這個Dialer值如果在30秒內(nèi)還沒有建立好網(wǎng)絡連接,那么就會被判定為操作超時。

在DefaultTransport的值被初始化的時候,這樣的Dialer值的DialContext方法會被賦給前者DialContext字段:

var DefaultTransport RoundTripper = &Transport{
	Proxy: ProxyFromEnvironment,
	DialContext: defaultTransportDialContext(&net.Dialer{
		Timeout:   30 * time.Second,
		KeepAlive: 30 * time.Second,
	}),
	ForceAttemptHTTP2:     true,
	MaxIdleConns:          100,
	IdleConnTimeout:       90 * time.Second,
	TLSHandshakeTimeout:   10 * time.Second,
	ExpectContinueTimeout: 1 * time.Second,
}

func defaultTransportDialContext(dialer *net.Dialer) func(context.Context, string, string) (net.Conn, error) {
	return dialer.DialContext
}

KeepAlive的背后是一種針對網(wǎng)絡連接(更確切地說,是TCP連接)的存活探測機制。它的值用于表示每隔多長時間發(fā)送一次探測包。當該值不大于0時,則表示不開啟這種機制。

DefaultTransport會把這個字段的值設定為30秒。

(2)http.Transport類型中的其它字段

一些是關于超時操作

  • IdleConnTimeout:含義是空閑的連接在多久之后就應該關閉。

 DefaultTransport 會把該字段的值設定為90秒。

如果該值為0,那么就表示不關閉空閑連接。注意,這樣可能會造成資源的泄露。

  • ResponseHeaderTimeout:含義是,從客戶端把請求完全遞交給操作系統(tǒng)到從操作系統(tǒng)那里接收到響應報文頭到最長時長。

 DefaultTransport并沒有設定該字段的值。

  •  ExpectContinueTimeout:含義是,在客戶端提交了請求報文頭之后,等待接收第一個響應報文頭的最長時間。

 DefaultTransport 把該字段的值設定為1秒。

在客戶端想要使用HTTP的“POST”方法把一個很大的報文體發(fā)送給服務端的時候,它可以先通過發(fā)送一個包含了“Expect: 100-continue”的請求報文頭,來詢問服務端是否愿意接受這個大報文體。這個字段就是用于設定在這種情況下的超時時間的。

注意,如果該字段的值不大于0,那么無論多大的請求報文體都將會被立即發(fā)送出去。

TLSHandshakeTimeout:TLS是Transport Layer Security 的縮寫,可以被翻譯為傳輸層安全。這個字段代表了基于TLS協(xié)議的連接在被建立時的握手階段的超時時間。

DefaultTransport 把該字段的值設置為10秒。

若該值為0,則表示對這個值不設限。

一些與IdleConnTimeout相關的字段值

  • MaxIdleConns:用于控制訪問所有主機的最大空閑連接。如果為0,不做限制。

DefaultTransport 把MaxIdleConns設定為100。

MaxIdleConns字段只會對空閑連接的總數(shù)做出限定。

  • MaxIdleConnsPerHost: 控制Transport值訪問每一個網(wǎng)絡服務的最大空閑連接數(shù)。如果為0,將使用缺省值2, 這個缺省值由DefaultMaxIdleConnsPerHost所代表。

也就是說,默認情況下,對于某一個Transport值訪問的每一個網(wǎng)絡服務,它的空閑連接數(shù)都最多只能由兩個。

  • MaxConnsPerHost:針對某一個Transport值訪問的每一個網(wǎng)絡服務的最大連接數(shù),不論這些連接是否是空閑的。

該字段沒有缺省值,零值表示不限定。

MaxIdleConns和MaxIdleConnsPerHost兩個與空閑連接數(shù)有關的字段的值應該是聯(lián)動的,所以,有時需要根據(jù)實際情況定制它們,可以參考DefaultTransport變量的聲明。

三、為什么會出現(xiàn)空閑的連接

3.1 空閑連接的產(chǎn)生

HTTP協(xié)議有一個請求報文頭,叫做“Connection”。在HTTP協(xié)議的1.1 版本中,這個報文頭的值默認是“keep-alive”。

在這種情況下,網(wǎng)絡連接都是持久連接,它們會在當前的HTTP事務完成后仍然保持著連通性,因此是可以被復用的。

連接的可復用,帶來兩種可能:

  • 一種可能是,針對同一個網(wǎng)絡服務,有新的HTTP請求被提交,該連接被再次使用。
  • 另一種可能是,不再有對該網(wǎng)絡服務的HTTP請求,該連接被閑置。(產(chǎn)生空閑的連接)

后一種情況就產(chǎn)生了空閑連接。另外,如果分配給某一個網(wǎng)絡服務的連接過多的話,也可能會導致空閑連接的產(chǎn)生。因為每一個新遞交的HTTP請求,都只會征用一個空閑的連接。所以,為空閑連接設定限制,在大多數(shù)情況下都是很有必要的,也是需要斟酌的。

3.2 杜絕空閑連接的產(chǎn)生

如果想徹底杜絕空閑連接的產(chǎn)生,那么可以在初始化的時候,把它的DisableKeepAlives字段的值設定為true。這時,HTTP請求的“Connection”報文頭的值就會被設置為“close”。這會告訴網(wǎng)絡服務,這個網(wǎng)絡連接不必保持,當前的HTTP事務完成后就可以斷開它。

如此一來,每當一個HTTP請求被遞交時,就會產(chǎn)生一個新的網(wǎng)絡連接。這樣做會明顯地加重網(wǎng)絡服務以及客戶端的負載。所以,在一般情況下,我們都不要去設置這個DisableKeepAlive字段。

在net.Dialer類型中,也有一個看起來很相似的字段KeepAlive。不過,它與前面所說的HTTP 持久連接不是一個概念,KeepAlive是直接作用在底層的socket上的。

KeepAlive的背后是一種針對網(wǎng)絡連接(更確切地說,是TCP連接)的存活探測機制。它的值用于表示每隔多長時間發(fā)送一次探測包。當該值不大于0時,則表示不開啟這種機制。DefaultTransport會把這個字段的值設定為30秒。

四、http.Server

http.Server類型與http.Client相對應。http.Server代表的是基于HTTP協(xié)議的服務端,或者網(wǎng)絡服務。

4.1 http.Server類型的ListenAndServe方法

http.Server類型的ListenAndServe方法的功能是:監(jiān)聽一個基于TCP協(xié)議的網(wǎng)絡地址,并對接收到的HTTP請求進行處理。

  • 這個方法默認會開啟針對網(wǎng)絡連接的存活探測機制,以保證連接是持久的。
  • 同時,該方法會一直執(zhí)行,直到有嚴重的錯誤發(fā)生或被外界關掉。

當被外界關掉時,它會返回一個由http.ErrServerClosed變量代表的錯誤值。

4.2 ListenAndServe方法主要做的事情

func (srv *Server) ListenAndServe() error {
	if srv.shuttingDown() {
		return ErrServerClosed
	}
	addr := srv.Addr
	if addr == "" {
		addr = ":http"
	}
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		return err
	}
	return srv.Serve(ln)
}

ListenAndServe方法主要會做下面的事情:

  • 檢查當前的http.Server類型的值的Addr字段。

該字段的值代表了當前的網(wǎng)絡服務需要使用的網(wǎng)絡地址。即:IP地址和端口號。如果這個字段的值為空字符串,那么就用":http"代替。

也就是說,使用任何可以代表本機的域名和IP地址,并且端口號為80.

  • 通過調(diào)用net.Listen函數(shù)在已確定的網(wǎng)絡地址上啟動基于TCP協(xié)議的監(jiān)聽。
  • 檢查net.Listen 函數(shù)返回的錯誤值。

如果該錯誤值不為nil,那么就直接返回該值。否則,通過調(diào)用當前值的Serve方法準備接受和處理將要到來的HTTP請求。

4.3 (衍生問題)net.Listen 函數(shù)都做了哪些事情

net.Listen函數(shù)做的事情:

  • 解析參數(shù)值中包含的網(wǎng)絡地址隱含的IP地址和端口號;
  • 根據(jù)給定的網(wǎng)絡協(xié)議,確定監(jiān)聽的方法,并開始進行監(jiān)聽;

這里還可以延伸到net.socket函數(shù),以及socket相關的知識。

4.4 (衍生問題)http.Server類型的Serve方法是怎么接受和處理HTTP請求的

在一個for循環(huán)中,網(wǎng)絡監(jiān)聽的Accept方法會被不斷的調(diào)用,

	for {
		rw, err := l.Accept()
  }

該方法會返回兩個結(jié)果值:

  • 第一個結(jié)果值是net.Conn 類型,代表包含了新到來的HTTP請求的網(wǎng)絡連接;
  • 第二個結(jié)果值是error類型值,代表可能發(fā)生的錯誤。

如果錯誤不為nil,除非它代表了一個暫時性的錯誤,否則循環(huán)都會被終止。如果是暫時性的錯誤,那么循環(huán)的下一次迭代將會在一段時間之后開始執(zhí)行。

如果這里的Accept方法沒有返回非nil的錯誤值,那么這里的程序?qū)阉牡谝粋€結(jié)果值包裝成一個*http.conn類型的值,然后通過在新的goroutine中調(diào)用這個*http.conn 類型值的serve方法,來對當前的HTTP請求進行處理。

HTTP請求相關的,更多的衍生問題:

  • 這個*http.conn類型值的狀態(tài)有幾種,分別代表著處理的哪個階段?
  • 處理的過程中會用到哪些讀取器和寫入器,它們的作用分別是什么?
  • 這里的程序是怎么調(diào)用我們自定義的處理函數(shù)的?

五、思考:怎么優(yōu)雅地停止基于HTTP協(xié)議的網(wǎng)絡服務程序?

srv.Shutdown(context.Background()) 的方式停止服務,通過RegisterOnShutdown可添加服務停止時的調(diào)用。

以上就是Golang中基于HTTP協(xié)議的網(wǎng)絡服務的詳細內(nèi)容,更多關于Golang HTTP協(xié)議的資料請關注腳本之家其它相關文章!

相關文章

  • Go設計模式之代理模式圖文詳解

    Go設計模式之代理模式圖文詳解

    這篇文章將通過圖文講解給大家詳細的介紹一下Go代理模式,代理模式是一種結(jié)構型設計模式,代理控制著對于原對象的訪問, 并允許在將請求提交給對象前后進行一些處理,感興趣的同學跟著小編一起來看看吧
    2023-07-07
  • 我為什么喜歡Go語言(簡潔的Go語言)

    我為什么喜歡Go語言(簡潔的Go語言)

    從2000年至今,也寫了11年代碼了,期間用過VB、Delphi、C#、C++、Ruby、Python,一直在尋找一門符合自己心意和理念的語言。我很在意寫代碼時的手感和執(zhí)行的效率,所以在Go出現(xiàn)之前一直沒有找到
    2014-10-10
  • go語言中range用法

    go語言中range用法

    這篇文章主要介紹了go語言中range用法,實例分析了Go語言中range的功能及使用技巧,需要的朋友可以參考下
    2015-03-03
  • 一文解析 Golang sync.Once 用法及原理

    一文解析 Golang sync.Once 用法及原理

    這篇文章主要介紹了一文解析 Golang sync.Once 用法及原理,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-08-08
  • Go流程控制代碼詳解

    Go流程控制代碼詳解

    這篇文章主要詳細介紹了Go流程控制,文章通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值 ,需要的朋友可以參考下
    2023-04-04
  • GO使用阿里云,解決go get下載項目慢或無法下載的情況

    GO使用阿里云,解決go get下載項目慢或無法下載的情況

    這篇文章主要介紹了GO使用阿里云,解決go get下載項目慢或無法下載的情況,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • 一文詳解Golang?定時任務庫?gron?設計和原理

    一文詳解Golang?定時任務庫?gron?設計和原理

    這篇文章主要介紹了一文詳解Golang?定時任務庫?gron?設計和原理,gron是一個比較小巧、靈活的定時任務庫,可以執(zhí)行定時的、周期性的任務。gron提供簡潔的、并發(fā)安全的接口
    2022-08-08
  • Go創(chuàng)建Grpc鏈接池實現(xiàn)過程詳解

    Go創(chuàng)建Grpc鏈接池實現(xiàn)過程詳解

    這篇文章主要為大家介紹了Go創(chuàng)建Grpc鏈接池實現(xiàn)過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • 解決Golang中goroutine執(zhí)行速度的問題

    解決Golang中goroutine執(zhí)行速度的問題

    這篇文章主要介紹了解決Golang中goroutine執(zhí)行速度的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05
  • Golang接入釘釘通知的示例代碼

    Golang接入釘釘通知的示例代碼

    本文主要介紹了Golang接入釘釘通知的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08

最新評論