網站首頁 編程語言 正文
引言
基于net
包的小應用
完整代碼已經上傳到github
GitHub-TCP
歡迎star
和issue
TCP介紹
特點
- 面向連接的運輸層協議。在應用程序在使用TCP協議之前,必須先建立TCP連接。在傳送數據完畢后,必須釋放已經建立的TCP連接。
- 每一條TCP連接只能有兩個端點,每一條TCP連接只能是點對點的。
- TCP提供可靠交付的服務。 通過TCP連接傳送的數據,無差錯,不丟失,不重復,并且按序到達。
- TCP提供全雙工通信。 TCP允許通信雙方的應用進程在任何時候都能發送數據。
- 面向字節流。 TCP的流是指流入到進程或從進程流出的字節序列。雖然應用程序和TCP的交互式一次一個數據塊,但TCP把應用程序交下來的數據僅僅看成是一連串的無結構的字節流。
圖解
- TCP結構
- TCP連接
TCP 連接建立,三次握手
傳輸控制塊TCB:存儲了每一個連接中的一些重要信息。比如TCP連接表,指向發送和接收緩沖的指針,指向重傳隊列的指針,當前的發送和接收序列等等。
假設主機A是TCP客戶程序,B是TCP服務器程序。最初兩端的TCP進程都是處于CLOSED關閉狀態,客戶端A打開鏈接,服務器端被打開鏈接。一開始B的TCP服務器進程先創建傳輸控制塊TCB,準備接受客戶進程的鏈接請求,然后服務器進程就處于LISTEN
收聽狀態,等待A的連接請求。
- 然后A的進程首先創建傳輸控制模塊TCB。向B發出連接請求報文段,這是首部當中的同步位
SYN=1
,同時選擇一個初始序號seq=x
。TCP規定,SYN報文段
(即SYN=1
的報文段)不能寫數據,但要消耗掉一個序號。這時候A就進入了同步已發送的狀態。 - B收到連接請求報文段后,如果同意建立連接,則向A發送確認,在確認報文段中把
SYN
位和AVK
位置都置為1
,確認號為ack+1
,同時也為自己選擇一個初始序號y。同樣的這個報文段也是不能寫數據的,但同時要消耗掉一個序號。這時B進入了同步收到狀態。 - A收到B的確認之后,還要向B給出確認。確認報文段的
ACK
置1,確認號ack=y+1
,而自己的seq=x+1
。ACK報文段是可以攜帶數據的,但如果不攜帶數據則不消耗序號,在這種情況下,下一個數據報文段的序號仍為seq=x+1
。
這時候TCP已經建立了。A進行入了已經建立連接的階段狀態。B收到確認后也進入了連接狀態。
TCP 連接釋放,四次揮手
數據傳輸完畢之后,通信的雙方都可釋放連接。現在A和B都處于ESTABLISHED
狀態。
- A的應用進程先向TCP發出連接釋放報文段,并停止再發送數據,主動關閉TCP連接。A把鏈接釋放報文段首部的終止控制位
FIN
置為1
,其序號為seq=u
,它等于前面以傳送過的數據的最后一個字節的序號加1
.這時候A進入了FIN-WAIT-1(終止等待1)
狀態,等待B的確認。
注意:TCP規定,FIN報文段即使不攜帶數據,他也消耗掉一個序號!!
- B 收到鏈接釋放報文段后即發出確認,確認號是
ack = u + 1
,而這個報文段自己的序號是v
,等于B前面已傳送過的數據的最后一個字節的序號加1
.然后B就進入CLOSE-WAIT(關閉等待)
狀態。TCP服務器進程這時應通知高層應用進程,因而從A到B這個方向的鏈接就釋放了,這時的TCP鏈接處于半關閉狀態,即A已經沒有數據要發送了,但B若發送數據,A仍要接收,也就是說,從B到A這個方向的連接并未關閉。這個狀態可能要維持一段時間。 - A收到來自B的確認后,就進入了
FIN-WAIT-2(終止等待2)
狀態滿等待B發出的連接釋放報文段。若B已經沒有要向A發送的數據,其應用進程就通知TCP釋放連接,這時B發出的連接釋放報文段必須使FIN = 1
,現假定B的序號為w
(在半關閉狀態B可能又發送了一些數據)。B還必須重復上次已發送過的確認號ack = u + 1
.這時B就進入LAST-ACK(最后確認)
狀態,等待A的確認。 - A在收到了B的鏈接釋放報文段后,必須對此發出確認。在確認報文段中把
ACK置1
,確認號ack=w+1
,而自己的序號是seq=u+1
(根據TCP標準,前面發送過的FIN報文段要消耗一個序號)。然后進入到TIME-WAIT
(時間等待)狀態。注意: 現在TCP連接還沒有還沒有釋放掉
。必須經過時間等待計時器設置的時間2MSL
后,A才能進入CLOSED狀態。
時間MSL叫做最長報文段壽命,RFC793建議設在兩分鐘。但是在現在工程來看兩分鐘太長了,所以TCP允許不同的實現可以根據具體情況使用更小的MSL值。
代碼實現
首先創建兩個目錄,一個是client
客戶端,另一個是server
服務端。
1. 連接
1.1 服務端
- 監聽連接
net
中提供了Listen
方法,可以讓服務端進行端口監聽
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
方法,讓客戶端連接服務端
ADDRESS := "127.0.0.1:5000" conn,err := net.Dial("tcp",ADDRESS) // 主動與服務端建立連接 if err != nil { fmt.Printf("dial %s failed; err :%s",ADDRESS,err) return }
2. 通信
2.1 服務端
- 接受信息
可以通過.Read
來讀取傳輸的數據。
var data [1024]byte var msg string reader := bufio.NewReader(os.Stdin) for { // 服務端要時刻等待傳送過來的數據,所以要用for循環 //接受信息 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 客戶端
- 發送信息
同樣可以通過.Write
在傳輸連接中傳輸數據。
for{ // 讓客戶的能一直發送信息,所以就需要一個for循環,保持連接 fmt.Print("請輸入:") msg,_ = reader.ReadString('\n') msg = strings.TrimSpace(msg) if msg == "exit" { break } _, _ = conn.Write([]byte(msg)) }
3. 回復
當服務端收到信息之后,應該返回信息給客戶端。表示已經收到了數據。
3.1 服務端
服務端回復信息
//回復信息 fmt.Print("回復信息:") 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("收到的回復:",string(data[:n]))
原文鏈接:https://juejin.cn/post/7034349674223894541
相關推薦
- 2022-07-06 C#使用ADO.Net連接數據庫與DbProviderFactory實現多數據庫訪問_C#教程
- 2022-06-22 Python?Tkinter?GUI編程實現Frame切換_python
- 2022-06-14 GO語言協程創建使用并通過channel解決資源競爭_Golang
- 2022-07-19 Python數據分析之?Pandas?Dataframe應用自定義_python
- 2023-01-03 C++定義和初始化string對象實例詳解_C 語言
- 2022-12-09 CALL命令無法在PowerShell中使用的原因及解決方法_DOS/BAT
- 2023-06-05 Python利用GDAL模塊實現讀取柵格數據并對指定數據加以篩選掩膜_python
- 2022-08-13 python 中導出requirements.txt 的幾種方法
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支