日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【转】运输层TCP协议详细介绍

發布時間:2025/3/18 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】运输层TCP协议详细介绍 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【轉】運輸層TCP協議詳細介紹

TCP是TCP/IP協議族中非常復雜的一個協議。它具有以下特點:

????1:面向連接的運輸層協議。在使用TCP協議之前,首先需要建立TCP連接。傳送數據完畢后,必須釋放已經建立的TCP連接。

????2:一條TCP連接有兩個端點,連接是點對點的。

????3:提供可靠交付的服務。通過TCP連接傳送的數據,不會出現差錯不會丟失并且按序到達。

????4:提供全雙工通信。TCP允許通信雙方的應用程序進程在任何時候都能發送數據。TCP連接的兩端都設有緩存,分為發送緩存和接收緩存,用來臨時存放雙向通信的數據。發送時,應用程序把數據傳給TCP的緩存后,就可以做自己的事情了。TCP會在合適的時候把數據發送出去。接收時,TCP把接收到的數據放入緩存,供上層的應用程序讀取。

????5:面向字節流。雖然應用程序和TCP的交互是一次一個數據塊,但TCP把應用程序交下來的數據看成一串無結構的字節流。TCP對應用進程一次把多長的報文發送到TCP緩存中是不關心的。TCP根據對方給出的窗口值和當前網絡的擁塞程度決定一個報文段包含多少字節。如果應用程序傳到TCP緩存的數據塊太長,TCP就會把它劃分短些再傳送。如果應用程序發來的數據太少時,TCP將會等待積累足夠多的字節后再構成報文段發送出去。

?

?? ?? TCP連接的端點叫做套接字。它是由IP和端口號構成。每一條TCP連接唯一的被通信兩端的兩個端點所確定。同一個IP地址可以有多個不同的TCP連接,而同一個端口號也可以出現在多個不同的TCP連接中。

???? TCP發送的報文段是交付給IP層傳送的,但IP層只提供盡最大努力的交付。也就是說TCP下面的網絡所提供的是不可靠的服務。可靠傳輸必須依靠TCP來實現。停止等待協議就是一種方式。

?

?? ? 停止等待就是每發送完一個分組就停止發送,等待接收方的確認,在收到確認后再傳送下一個分組。如果發送方在一段時間后仍然沒有收到確認,就認為剛才發送的分組丟失了,因而重傳前面發送過的分組,這被稱為超時重傳。要實現超時重傳,就要在每發送完一個分組后設置一個超時計時器。如果在超時計時器到期之前收到了對方的確認,就撤銷已設置的超時計時器。因此發送方在發送完一個分組之后,必須暫時保存已發送的分組的副本。只有在收到響應的確認后才能清除暫時保留的分組的副本。分組和確認分組都必須進行編號,這樣才能知道哪一個發送過的數據已被確認,那些沒有收到確認。超時計時器設置的重傳時間應該比數據在分組傳輸的平均往返時間更長一些。超時重傳時間的設定是非常復雜的,因為已發送的分組到底經過那些網絡,以及這些網絡會產生多大的延遲都是不確定的。

?

??????? 如果發送方發送了數據后,在超時時間內沒有收到接收方的確認,它會重傳數據。如果此時接受方再次接收到了此數據,它會將此數據丟棄,并向發送方發送確認。發送方沒有收到確認,可能是因為接受方的確認出錯或丟失。發送方還可能收到重復的確認,對待重復的確認只需要丟棄即可。上述可靠的傳輸協議被稱為自動重傳請求ARQ(Automatic?Repeat?Request)。采用停止等待協議可能會導致信道利用率非常低,為了提高傳輸效率,需要使用流水線傳輸。也就是說發送方可以連續發送多個分組,不必沒發完一個分組就停下來等待對方的確認。這樣可以使信道上一直有數據不間斷的在傳送。這被稱為連續ARQ協議或滑動窗口協議。它比較復雜但卻是TCP協議的精髓。

?

?????? 所謂滑動窗口就是說位于此窗口內的分組可以被連續的發送出去,而不需要等待對方的確認。發送方每收到一個確認,就會把發送窗口向前滑動一個分組的位置。假設此時1-5個分組位于發送窗口內,這5個分組就會被連續的發送出去。當發送方收到第一個分組的確認后,就會向后移動一個分組的位置,此時就可以發送第六個分組了。接收方一般都采用累積確認的方式。也就是說,接收方不必對收到的每個分組逐個發送確認,而是可以收到幾個分組后,對按序到達的最后一個分組發送確認。這樣就表示到這個分組為止的所有分組都被正確接收。如果此時發送方發送了前5個分組,而第三個分組丟失了,這是接收方只能對前兩個分組發送確認。發送方不知道后面三個分組的下落。實際上僅僅第三個分組沒有收到,但是發送方仍然會發送后三個分組。

?

?? ? TCP是面向字節流的,但是TCP傳送的數據卻是報文段。一個TCP報文段分為首部和數據兩部分。只有真正弄清TCP的首部各字段的作用才能掌握TCP的原理。

?? ? TCP的前20個字節是固定的。后面的40字節是根據需要增加的。因此TCP首部的最小長度時20。

???? 1:源端口和目的端口:各占兩個字節。

???? 2:序號:四個字節。共2的32次方個序號。TCP連接中傳送的字節流中的每一個字節都按順序編號。此處的序號字段指的是本報文段所發送的數據第一個字節的序號。

???? 3:確認號:4個字節。表示期望收到對方下一個報文段的第一個數據字節的序號。如確認號是N,則表明序號N-1之前的數據都正確收到。確認號也是4個字節,可以對4GB數據進行編號。

?? ? 4:數據偏移,4位。它指出TCP報文段的數據起始處距離TCP報文段起始處有多遠。這個字段實際上指出了TCP的首部。由于首部中有長度不確定的選項字段,因此此數據偏移是必要的。數據偏移只有4位,但是它的一個單位代表4字節。因此數據偏移的最大值是60(15*4)。即TCP首部的最大長度。

???? 5:保留?6位。保留為以后使用。都是0.

???? 6:緊急URG?當此處為1時,表明緊急指針字段有效。它告訴系統此報文段有緊急數據,需要盡快傳送。系統會把緊急數據插入TCP緩存的最前面。它和緊急指針字段配合使用。

???? 7:確認ACK:當ACK=1時,確認號字段才有效。當ACK=0時確認號無效。當連接建立前ACK=0,建立之后ACK就一直是1了。

???? 8:推送PSH。當PSH=1時,系統會立即將此報文段發送出去,而不再等待整個緩存都被填滿后才向上交付。

???? 9:復位RST。當其為1,時,表明TCP出現嚴重錯誤,必須釋放連接然后再重新建立連。

???? 10:同步SYN:在連接建立時用來同步序號。當其為1而ACK=0時,表明這是一個(同步)連接請求報文段。當對方同意后,應在響應報文段中使用SYN=1,ACK=1。因此SYN=1,要么表示連接請求要么表示連接接受報文。

?? ? 11:終止FIN:用來釋放連接。當其為1時,表明此報文段的發送方的數據已經發送完畢,要求釋放連接。

?? ? 12:窗口:2字節。窗口指發送方的接收窗口。它告訴對方:從本報文段首部中的確認號算起,接收方目前允許對方發送的數據量。之所以有此限制是因為接收方的數據緩存空間是有限的。它指出現在允許對方發送數據量。由于接收緩存不斷變化,因此窗口值也不斷變化。

???? 13:檢驗和:2字節。檢驗和檢驗?的是首部和數據這兩部分。在計算時還應加上12字節的偽首部。

???? 14:緊急指針:2字節,此字段只在緊急URG=1時才有意義。它指出本報文段中緊急數據的字節數。由于緊急數據放在了緩沖區最前方,緊急指針指出的是緊急數據的末尾在報文段的位置。當所有的緊急數據都處理完后,TCP?就告訴應用程序恢復正常操作。

???? 15:選項:長度可變,最長可達40字節。當沒有選項時,首部長度時20.

?

?? ? MSS是選項的一種。它被稱為最大報文段長度,是每個TCP報文段中數據字段的最大長度。它加上TCP首部才是整個TCP報文段。再加上20字節的IP首部才能組裝成一個IP數據報。當MSS非常小時,網絡的利用率就低。如果發送只含一個字節的數據時,在IP層傳輸至少需要40字節的開銷(IP頭20字節,TCP頭至少20)。到鏈路層還需要開銷。如果MSS非常大,在IP層傳輸時就可能要分片,到終點后再將各個分片組裝成原來的TCP報文段,這也會使開銷增大。因此,MSS可以盡量大,只要在IP層傳輸時不分片就行了。MSS的默認長度時536。

????窗口擴大選項是為了擴大窗口,窗口字段長度是16位,因此最大的窗口大小是64字節。窗口擴大選項占3個字節。每一個字節表示移位值。新的窗口值等于原來的16+窗口擴大選項的值。這相當于把窗口值向左移動移位值位。

????時間戳選項占10字節,最主要的兩個地段是:時間戳值和時間戳回送回答字段。

時間戳選項具有以下兩個功能

????1:計算往返時間。

????2:用于處理TCP序號超過2的32次方的情況。這又被稱為防止序號繞回。在報文段中加入時間戳就可以區分新的報文段和遲到很久的報文段。

?

????socket的兩端分別有兩個窗口,發送窗口和接收窗口。滑動窗口的單位是字節,假設A收到了B的確認報文段,其中窗口時20,而確認號是31,這表明B期望接受的下一個序號是31,到序號30為止的數據已經收到了。根據這兩個數據,A就構造自己的發送窗口。它的起始值為31,而末尾值為50。發送窗口表示在沒有收到B的確認前,A可以連續把窗口內的數據都發送出去。

?

???? 凡是已經發送過得數據,在未收到確認之前都必須暫時保留,以便在在超時重傳。發送窗口內的序號表示允許發送的序號。

?? ? 發送窗口與緩存的關系。

???? 發送窗口存儲應用程序將要發送的數據,以及發送但卻為收到確認的數據。?發送窗口只是發送緩存的一部分,已經被確認過的數據應當從發送緩存中刪除。因此發送緩存和發送窗口的后沿是重合的。

接收緩存用來暫時存放按需到達的,但還未被應用程序讀取的數據以及未按序到達的數據。?如果收到的分組有差錯,就要丟棄。如果接收應用程序來不及讀取,接收緩存就會被填滿,就會減少接受窗口,直到減為0。反之就可以增大。

???? 雖然發送方的發送窗口是根據接收方方接收窗口設置但是,但同一時刻,發送窗口并不一定與接收窗口相同。這是因為通過網絡傳送窗口值需要經歷一定的延遲。

?? ? TCP要求接收方必須有累計確認的功能,這樣可以減小傳輸開銷。接收方可以在合適的時候發送確認,也可以在自己有數據發送時把確認信息捎上。但應該注意的是接收方不應過分推遲發送確認,否則會導致發送方不必要的重傳,這反而會浪費網絡資源。

?????TCP利用滑動窗口來實現流量控制。所謂流量控制就是讓發送方的發送速率不要太快,要讓接收方來得及接受。在連接建立時,發送方告訴接收方我的接受窗口是x,接收方收到后會設置自己的發送窗口。發送方的發送窗口不能超過接收方給出的接收窗口的數值。TCP窗口的單位是字節,而不是報文段。在每次發送數據是報文段內會將此時接受窗口告訴發送者。發送者會根據收到的報文段接收窗口的值調整自己的發送窗口。當接收方接收緩存滿時就發送給發送方零窗口,告訴發送方停止發送。假設過一段時間接收方調整接收窗口為100,而此報文段在傳送過程中丟失,這就導致發送方等待接收方的非零窗口通知,而接收方在等待發送方的數據。這樣就導致了死鎖。為了防止這種情況,TCP為每個連接設置一個持續計時器。TCP連接的一方收到零窗口通知后,就啟動計時器,設置的時間到期后它會發送一個探測報文段。如果此時返回的仍然是零窗口,則重新設定計時器。如果窗口不是零,那么死鎖的僵局就可以被打破了。

?

????? TCP是面向連接的協議。分為三個階段:

????? 一:連接建立

????? 二:數據傳送

????? 三:連接釋放。

?

????在TCP連接建立的過程中需要解決一下三個問題:

????1:要使每一方能夠通知對方的存在。

????2:允許雙方協商一些參數。如窗口最大值、是否使用窗口擴大選項和時間戳選項。

??? 3:能夠對運輸實體資源,如緩存進行分配。

?

??? TCP連接的建立采取客戶服務器方式。主動發起連接的叫做客戶。被動等待連接建立的應用程序叫做服務器。

?

????TCP的建立連接需要客戶服務器通信三次。這就是常說的三次握手。

????首先服務器創建socket,綁定端口并進入監聽模式等待客戶端的請求。客戶端B向服務器發送連接請求報文段。此時同部位SYN=1,初始序號seq=x,ACK=0(連接未建立,確認字段無效)。此時客戶端進入同步--已發送狀態。

????服務器收到連接請求,如同意建立連接,則會發送確認。此時SYN=1,ACK=1,確認號ack=x+1。設置自己的初始序號seq=y。此時服務器進入同步--收到狀態。

????客戶端收到確認后,還要給服務器進行確認,此時ACK=1,ack=y+1.seq=x+1。此時的報文段已經可以攜帶數據了。此時客戶端進入已經建立狀態。

????服務器收到后也進入已建立狀態。

?

????? 很多人會很疑問會什么客戶端還需要發送一次確認,這主要是防止已失效的連接請求報文段突然又傳送到服務器。比如客戶端發出連接請求,但此請求丟失,沒有收到服務器發來的額確認。于是一段時間后客戶端繼續請求,此請求被服務器接收,客戶端收到了服務器的請求。數據傳輸完畢后,連接被釋放。如果此時客戶端第一次發送的報文段在網絡中滯留一段時間后到達服務器,服務器收到這個失效的請求,卻誤以為是客戶端發出的新的連接請求。于是向客戶端發送同一連接請求。由于客戶端沒有發出連接請求,當然會將此報文丟棄。而服務器卻一直等待客戶端的回復。

????? TCP連接的釋放。

????? 數據傳輸結束后任何一方都可以申請釋放連接。A向B發送連接釋放報文段,并停止發送數據。主動關閉TCP連接。此時?A的連接釋放報文段首部FIN應置為1,序號seq=x,等于前面已傳送過得數據的最后一個序號加一。此時A進入終止--等待(FIN-WAIT-1)狀態1。等待B的確認。TCP規定FIN報文段即使不攜帶數據也要消耗一個序號。

B收到連接釋放報文段后即發出確認,確認號ack是x+1。seq=y。然后B就進入了關閉--等待(CLOSE_WAIT)狀態。此時?從A到B這個方向的連接已經釋放了,這是TCP處于半關閉狀態。即A不會在發送數據,但B要發送數據A?仍要接收。A收到B的確認后就進入了終止--等待(FIN-WAIT-2)狀態2,等待B發出的連接釋放報文段。若B沒有?數據要發送給A,它發出連接釋放報文段將FIN置為1,ACK=1,seq=w,ack=u+1.此時B處于最后確認狀態。?等待A的確認。A在收到B的連接釋放報文段后,必須對此進行確認。將ACK置為1,確認號ack=w+1,?seq=u+1。然后進入時間--等待(TIME-WAIT)狀態,此時TCP連接還沒有被釋放,還必須經過時間計時器設置的2MSL后?A才進入關閉狀態。MSL為Maximum?segment?Lifetime。即最長報文段壽命。

?

?????? 之所以要設置這個最大報文段壽命,有兩個原因:

?????? 1:為保證A發送的最后一個ACK報文能夠到達B。因為它有可能丟失,此時便導致B收不到對方對FIN+ACK報文段的確認。此后B會超時重傳。由于A設置了2MSL計時器,使得A有機會收到B的報文。如果A不設置2MSL,而是發送完ACK報文段后立即釋放,就無法收到B重傳的FIN+ACK報文段。B也就無法按正常步驟進入CLOSED狀態。

?????? 2:防止已失效的連接請求報文段出現。A發送完最后一個ACK報文段后,等待2MSL就可使本此連接所產生的所有報文段都從網絡中消失,不會對下一次的連接造成影響。

?????? 除等待計時器外,TCP還設置一個保活計時器。如果客戶端主動與服務器建立起連接,而此后客戶端突然出現故障,此后服務器不能收到從客戶端發來的數據,此時應采取一定的措施,是服務器不白白等待。服務器每收到一次客戶端的數據就重置保活計時器,時間通常是2小時。若兩小時沒有收到客戶端的數據,服務器就發送探測報文,以后每隔75分鐘發送一次,若一連發送10探測報文段后仍無客戶端的響應,服務器就認為客戶端出現故障,接著就關閉了連接。

?????? 在客戶--服務器模型中,通常務器分配的一個socket對某一端口進行監聽。一旦監聽到有連接請求。就調用accept,accept將會產生新的socket。然后服務器創建新的線程,新的socket將會作為新線程的參數。系統會為這個新的socket分配一個服務器端的自由端口號,這個套接字專用于在連接建立后與客戶端交換數據。它一般被稱為響應套接字。

? 看一個例子:

?

  • SADATA wsd;
  • int err;
  • err=WSAStartup(MAKEWORD(2,2), &wsd);
  • if(err!=0)//網絡有問題
  • {
  • printf("發生未知網絡錯誤,程序將退出");
  • return 0;
  • }
  • SOCKET ListenSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);;
  • struct sockaddr_in local,client;
  • int iAddrSize;
  • local.sin_addr.s_addr = htonl(INADDR_ANY);
  • local.sin_family = AF_INET;
  • local.sin_port = htons(80);
  • if(bind(ListenSocket, (struct sockaddr *)&local,sizeof(local))==SOCKET_ERROR)//綁定到80端口。
  • {
  • printf("bind error\r\n");
  • return 0;
  • }
  • if(listen(ListenSocket, SOMAXCONN)==SOCKET_ERROR)//監聽失敗
  • {
  • printf("Listen error!\n");
  • }
  • printf("Listen on 80!\n");
  • int num=1;
  • while(1)
  • {
  • iAddrSize = sizeof(client);
  • SOCKET sServerSocket = accept(ListenSocket,(struct sockaddr *)&client,&iAddrSize);
  • if(sServerSocket!=INVALID_SOCKET)
  • {
  • printf("IP: %s 連接\r\n",inet_ntoa(client.sin_addr));
  • DWORD TID;
  • HANDLE hHandle= CreateThread(NULL,NULL,RecvThreadDirect,(LPVOID)sServerSocket,0,&TID);//創建線程處理請求,參數為請求連接的socket。
  • printf("創建第%d個線程",num);
  • num++;
  • //WaitForSingleObject(hHandle,INFINITE);
  • CloseHandle(hHandle);
  • Sleep(100);
  • }
  • else
  • break;
  • }
  • ?

  • posted on 2018-07-17 23:14 時空觀察者9號 閱讀(...) 評論(...) 編輯 收藏

    總結

    以上是生活随笔為你收集整理的【转】运输层TCP协议详细介绍的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。