亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Go語(yǔ)言TCP從原理到代碼實(shí)現(xiàn)詳解

 更新時(shí)間:2022年08月22日 10:11:56   作者:小生凡一  
這篇文章主要為大家介紹了Go語(yǔ)言TCP從原理到代碼實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

基于net包的小應(yīng)用

完整代碼已經(jīng)上傳到github GitHub-TCP

歡迎starissue

TCP介紹

特點(diǎn)

  • 面向連接的運(yùn)輸層協(xié)議。在應(yīng)用程序在使用TCP協(xié)議之前,必須先建立TCP連接。在傳送數(shù)據(jù)完畢后,必須釋放已經(jīng)建立的TCP連接。
  • 每一條TCP連接只能有兩個(gè)端點(diǎn),每一條TCP連接只能是點(diǎn)對(duì)點(diǎn)的。
  • TCP提供可靠交付的服務(wù)。 通過(guò)TCP連接傳送的數(shù)據(jù),無(wú)差錯(cuò),不丟失,不重復(fù),并且按序到達(dá)。
  • TCP提供全雙工通信。 TCP允許通信雙方的應(yīng)用進(jìn)程在任何時(shí)候都能發(fā)送數(shù)據(jù)。
  • 面向字節(jié)流。 TCP的流是指流入到進(jìn)程或從進(jìn)程流出的字節(jié)序列。雖然應(yīng)用程序和TCP的交互式一次一個(gè)數(shù)據(jù)塊,但TCP把應(yīng)用程序交下來(lái)的數(shù)據(jù)僅僅看成是一連串的無(wú)結(jié)構(gòu)的字節(jié)流。

圖解

  • TCP結(jié)構(gòu)

  • TCP連接

TCP 連接建立,三次握手

傳輸控制塊TCB:存儲(chǔ)了每一個(gè)連接中的一些重要信息。比如TCP連接表,指向發(fā)送和接收緩沖的指針,指向重傳隊(duì)列的指針,當(dāng)前的發(fā)送和接收序列等等。

假設(shè)主機(jī)A是TCP客戶程序,B是TCP服務(wù)器程序。最初兩端的TCP進(jìn)程都是處于CLOSED關(guān)閉狀態(tài),客戶端A打開(kāi)鏈接,服務(wù)器端被打開(kāi)鏈接。一開(kāi)始B的TCP服務(wù)器進(jìn)程先創(chuàng)建傳輸控制塊TCB,準(zhǔn)備接受客戶進(jìn)程的鏈接請(qǐng)求,然后服務(wù)器進(jìn)程就處于LISTEN收聽(tīng)狀態(tài),等待A的連接請(qǐng)求。

  • 然后A的進(jìn)程首先創(chuàng)建傳輸控制模塊TCB。向B發(fā)出連接請(qǐng)求報(bào)文段,這是首部當(dāng)中的同步位SYN=1,同時(shí)選擇一個(gè)初始序號(hào)seq=x。TCP規(guī)定,SYN報(bào)文段(即SYN=1的報(bào)文段)不能寫(xiě)數(shù)據(jù),但要消耗掉一個(gè)序號(hào)。這時(shí)候A就進(jìn)入了同步已發(fā)送的狀態(tài)。
  • B收到連接請(qǐng)求報(bào)文段后,如果同意建立連接,則向A發(fā)送確認(rèn),在確認(rèn)報(bào)文段中把SYN位和AVK位置都置為1,確認(rèn)號(hào)為ack+1,同時(shí)也為自己選擇一個(gè)初始序號(hào)y。同樣的這個(gè)報(bào)文段也是不能寫(xiě)數(shù)據(jù)的,但同時(shí)要消耗掉一個(gè)序號(hào)。這時(shí)B進(jìn)入了同步收到狀態(tài)。
  • A收到B的確認(rèn)之后,還要向B給出確認(rèn)。確認(rèn)報(bào)文段的ACK置1,確認(rèn)號(hào)ack=y+1,而自己的seq=x+1。ACK報(bào)文段是可以攜帶數(shù)據(jù)的,但如果不攜帶數(shù)據(jù)則不消耗序號(hào),在這種情況下,下一個(gè)數(shù)據(jù)報(bào)文段的序號(hào)仍為seq=x+1。

這時(shí)候TCP已經(jīng)建立了。A進(jìn)行入了已經(jīng)建立連接的階段狀態(tài)。B收到確認(rèn)后也進(jìn)入了連接狀態(tài)。

TCP 連接釋放,四次揮手

數(shù)據(jù)傳輸完畢之后,通信的雙方都可釋放連接?,F(xiàn)在A和B都處于ESTABLISHED狀態(tài)。

  • A的應(yīng)用進(jìn)程先向TCP發(fā)出連接釋放報(bào)文段,并停止再發(fā)送數(shù)據(jù),主動(dòng)關(guān)閉TCP連接。A把鏈接釋放報(bào)文段首部的終止控制位FIN置為1,其序號(hào)為seq=u,它等于前面以傳送過(guò)的數(shù)據(jù)的最后一個(gè)字節(jié)的序號(hào)加1.這時(shí)候A進(jìn)入了FIN-WAIT-1(終止等待1)狀態(tài),等待B的確認(rèn)。

注意:TCP規(guī)定,F(xiàn)IN報(bào)文段即使不攜帶數(shù)據(jù),他也消耗掉一個(gè)序號(hào)??!

  • B 收到鏈接釋放報(bào)文段后即發(fā)出確認(rèn),確認(rèn)號(hào)是ack = u + 1,而這個(gè)報(bào)文段自己的序號(hào)是v,等于B前面已傳送過(guò)的數(shù)據(jù)的最后一個(gè)字節(jié)的序號(hào)加1.然后B就進(jìn)入CLOSE-WAIT(關(guān)閉等待)狀態(tài)。TCP服務(wù)器進(jìn)程這時(shí)應(yīng)通知高層應(yīng)用進(jìn)程,因而從A到B這個(gè)方向的鏈接就釋放了,這時(shí)的TCP鏈接處于半關(guān)閉狀態(tài),即A已經(jīng)沒(méi)有數(shù)據(jù)要發(fā)送了,但B若發(fā)送數(shù)據(jù),A仍要接收,也就是說(shuō),從B到A這個(gè)方向的連接并未關(guān)閉。這個(gè)狀態(tài)可能要維持一段時(shí)間。
  • A收到來(lái)自B的確認(rèn)后,就進(jìn)入了FIN-WAIT-2(終止等待2)狀態(tài)滿等待B發(fā)出的連接釋放報(bào)文段。若B已經(jīng)沒(méi)有要向A發(fā)送的數(shù)據(jù),其應(yīng)用進(jìn)程就通知TCP釋放連接,這時(shí)B發(fā)出的連接釋放報(bào)文段必須使FIN = 1,現(xiàn)假定B的序號(hào)為w(在半關(guān)閉狀態(tài)B可能又發(fā)送了一些數(shù)據(jù))。B還必須重復(fù)上次已發(fā)送過(guò)的確認(rèn)號(hào)ack = u + 1.這時(shí)B就進(jìn)入LAST-ACK(最后確認(rèn))狀態(tài),等待A的確認(rèn)。
  • A在收到了B的鏈接釋放報(bào)文段后,必須對(duì)此發(fā)出確認(rèn)。在確認(rèn)報(bào)文段中把ACK置1,確認(rèn)號(hào)ack=w+1,而自己的序號(hào)是seq=u+1(根據(jù)TCP標(biāo)準(zhǔn),前面發(fā)送過(guò)的FIN報(bào)文段要消耗一個(gè)序號(hào))。然后進(jìn)入到TIME-WAIT(時(shí)間等待)狀態(tài)。注意: 現(xiàn)在TCP連接還沒(méi)有還沒(méi)有釋放掉。必須經(jīng)過(guò)時(shí)間等待計(jì)時(shí)器設(shè)置的時(shí)間2MSL后,A才能進(jìn)入CLOSED狀態(tài)。

時(shí)間MSL叫做最長(zhǎng)報(bào)文段壽命,RFC793建議設(shè)在兩分鐘。但是在現(xiàn)在工程來(lái)看兩分鐘太長(zhǎng)了,所以TCP允許不同的實(shí)現(xiàn)可以根據(jù)具體情況使用更小的MSL值。

代碼實(shí)現(xiàn)

首先創(chuàng)建兩個(gè)目錄,一個(gè)是client客戶端,另一個(gè)是server服務(wù)端。

1. 連接

1.1 服務(wù)端

  • 監(jiān)聽(tīng)連接

net 中提供了Listen方法,可以讓服務(wù)端進(jìn)行端口監(jiān)聽(tīng)

ADDRESS := "127.0.0.1:5000"
listener,err := net.Listen("tcp",ADDRESS)
if err != nil {
	fmt.Printf("start tcp server %s failed ,err : %s ",listener,err)
	return
}
defer listener.Close()

1.2 客戶端

  • 建立連接

net中提供了Dail方法,讓客戶端連接服務(wù)端

ADDRESS := "127.0.0.1:5000"
conn,err := net.Dial("tcp",ADDRESS) // 主動(dòng)與服務(wù)端建立連接
if err != nil {
	fmt.Printf("dial %s failed; err :%s",ADDRESS,err)
	return
}

2. 通信

2.1 服務(wù)端

  • 接受信息

可以通過(guò).Read來(lái)讀取傳輸?shù)臄?shù)據(jù)。

	var data [1024]byte
	var msg string
	reader := bufio.NewReader(os.Stdin)
	for {   // 服務(wù)端要時(shí)刻等待傳送過(guò)來(lái)的數(shù)據(jù),所以要用for循環(huán)
		//接受信息
		n,err := conn.Read(data[:])
		if err == io.EOF{
			break
		}
		if err != nil {
			fmt.Printf("read from conn failed,err:%s",err)
			return
		}
		fmt.Println("Access Info : ",string(data[:n]))
	}
	defer conn.Close()

2.2 客戶端

  • 發(fā)送信息

同樣可以通過(guò).Write在傳輸連接中傳輸數(shù)據(jù)。

	for{ // 讓客戶的能一直發(fā)送信息,所以就需要一個(gè)for循環(huán),保持連接
		fmt.Print("請(qǐng)輸入:")
		msg,_ = reader.ReadString('\n')
		msg = strings.TrimSpace(msg)
		if msg == "exit" {
			break
		}
		_, _ = conn.Write([]byte(msg))
	}

3. 回復(fù)

當(dāng)服務(wù)端收到信息之后,應(yīng)該返回信息給客戶端。表示已經(jīng)收到了數(shù)據(jù)。

3.1 服務(wù)端

服務(wù)端回復(fù)信息

	//回復(fù)信息
	fmt.Print("回復(fù)信息:")
	msg,_ = reader.ReadString('\n')
	msg = strings.TrimSpace(msg)
	if msg == "exit" {
		break
	}
	_ ,_ = conn.Write([]byte(msg))

3.2 客戶端

客戶端收到信息

	// 接受信息
	n,err:=conn.Read(data[:])
	if err == io.EOF {
		break
	}
	if err != nil {
		fmt.Println("read from conn failed, err :",err)
		return
	}
	fmt.Println("收到的回復(fù):",string(data[:n]))

以上就是Go語(yǔ)言TCP從原理到代碼實(shí)現(xiàn)詳解的詳細(xì)內(nèi)容,更多關(guān)于Go TCP原理代碼的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Golang字符串變位詞示例詳解

    Golang字符串變位詞示例詳解

    這篇文章主要給大家介紹了關(guān)于GoLang字符串變位詞的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-10-10
  • 阿里云go開(kāi)發(fā)環(huán)境搭建過(guò)程

    阿里云go開(kāi)發(fā)環(huán)境搭建過(guò)程

    這篇文章主要介紹了阿里云go開(kāi)發(fā)環(huán)境搭建過(guò)程,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2018-02-02
  • golang中range在slice和map遍歷中的注意事項(xiàng)

    golang中range在slice和map遍歷中的注意事項(xiàng)

    今天小編就為大家分享一篇關(guān)于golang中range在slice和map遍歷中的注意事項(xiàng),小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-04-04
  • Golang在Mac、Linux、Windows下如何交叉編譯的實(shí)現(xiàn)

    Golang在Mac、Linux、Windows下如何交叉編譯的實(shí)現(xiàn)

    這篇文章主要介紹了Golang在Mac、Linux、Windows下如何交叉編譯的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • GO語(yǔ)言協(xié)程互斥鎖Mutex和讀寫(xiě)鎖RWMutex用法實(shí)例詳解

    GO語(yǔ)言協(xié)程互斥鎖Mutex和讀寫(xiě)鎖RWMutex用法實(shí)例詳解

    這篇文章主要介紹了GO語(yǔ)言協(xié)程互斥鎖Mutex和讀寫(xiě)鎖RWMutex用法詳解,需要的朋友可以參考下
    2022-04-04
  • Golang中crypto/ecdsa庫(kù)實(shí)現(xiàn)數(shù)字簽名和驗(yàn)證

    Golang中crypto/ecdsa庫(kù)實(shí)現(xiàn)數(shù)字簽名和驗(yàn)證

    本文主要介紹了Golang中crypto/ecdsa庫(kù)實(shí)現(xiàn)數(shù)字簽名和驗(yàn)證,將從ECDSA的基本原理出發(fā),詳細(xì)解析如何在Go語(yǔ)言中實(shí)現(xiàn)數(shù)字簽名和驗(yàn)證,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02
  • golang高并發(fā)的深入理解

    golang高并發(fā)的深入理解

    golang從語(yǔ)言級(jí)別上對(duì)并發(fā)提供了支持,而且在啟動(dòng)并發(fā)的方式上直接添加了語(yǔ)言級(jí)的關(guān)鍵字。下面這篇文章主要給大家介紹了關(guān)于golang高并發(fā)的相關(guān)資料,需要的朋友可以參考下
    2019-03-03
  • Golang并發(fā)繞不開(kāi)的重要組件之Channel詳解

    Golang并發(fā)繞不開(kāi)的重要組件之Channel詳解

    Channel是一個(gè)提供可接收和發(fā)送特定類型值的用于并發(fā)函數(shù)通信的數(shù)據(jù)類型,也是Golang并發(fā)繞不開(kāi)的重要組件之一,本文就來(lái)和大家深入聊聊Channel的相關(guān)知識(shí)吧
    2023-06-06
  • Golang實(shí)現(xiàn)WebSocket服務(wù)的項(xiàng)目實(shí)踐

    Golang實(shí)現(xiàn)WebSocket服務(wù)的項(xiàng)目實(shí)踐

    本文介紹如何使用Golang實(shí)現(xiàn)實(shí)時(shí)后端WebSocket服務(wù),首先使用Gin框架搭建http服務(wù),然后使用gorilla/websocket庫(kù)實(shí)現(xiàn)簡(jiǎn)單后端WebSocket服務(wù),具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-05-05
  • Golang拾遺之自定義類型和方法集詳解

    Golang拾遺之自定義類型和方法集詳解

    golang拾遺主要是用來(lái)記錄一些遺忘了的、平時(shí)從沒(méi)注意過(guò)的golang相關(guān)知識(shí)。這篇文章主要整理了一下Golang如何自定義類型和方法集,需要的可以參考一下
    2023-02-02

最新評(píng)論