tcp(傳輸層)
TCP(Transmission Control Protocol 傳輸控制協議)是一種面向連接的、可靠的、基于字節流的傳輸層通信協議,由IETF的RFC 793定義。在簡化的計算機網絡OSI模型中,它完成第四層傳輸層所指定的功能,用戶數據報協議(UDP)是同一層內 另一個重要的傳輸協議。在因特網協議族(Internet protocol suite)中,TCP層是位于IP層之上,應用層之下的中間層。不同主機的應用層之間經常需要可靠的、像管道一樣的連接,但是IP層不提供這樣的流機制,而是提供不可靠的包交換。
應用層向TCP層發送用于網間傳輸的、用8位字節表示的數據流,然后TCP把數據流分區成適當長度的報文段(通常受該計算機連接的網絡的數據鏈路層的最大傳輸單元( MTU)的限制)。之后TCP把結果包傳給IP層,由它來通過網絡將包傳送給接收端實體 的TCP層。TCP為了保證不發生丟包,就給每個包一個序號,同時序號也保證了傳送到接收端實體的包的按序接收。然后接收端實體對已成功收到的包發回一個相應的確認(ACK);如果發送端實體在合理的往返時延(RTT)內未收到確認,那么對應的數據包就被假設為已丟失將會被進行重傳。TCP用一個校驗和函數來檢驗數據是否有錯誤;在發送和接收時都要計算校驗和。
三次握手
TCP是因特網中的傳輸層協議,使用三次握手協議建立連接。當主動方發出SYN連接請求后,等待對方回答SYN+ACK ,并最終對對方的 SYN 執行 ACK 確認。這種建立連接的方法可以防止產生錯誤的連接,TCP使用的流量控制協議是可變大小的滑動窗口協議。 TCP三次握手的過程如下:
- 客戶端發送SYN(SEQ=x)報文給服務器端,進入SYN_SEND狀態。
- 服務器端收到SYN報文,回應一個SYN (SEQ=y)ACK(ACK=x+1)報文,進入SYN_RECV狀態。
- 客戶端收到服務器端的SYN報文,回應一個ACK(ACK=y+1)報文,進入Established狀態。
連接成功
連接成功之后雙方即可互相傳輸字節流,并隨時可關閉連接,傳輸的數據有以下特性
-
傳輸的數據被tcp分割成了最適合發送的數據塊 傳遞給ip協議,這個發送數據稱為 報文段 或 段
-
tcp作為可靠性連接,每次發送數據段,會啟動一個定時器,每次接收數據段,會發送一次確認,如果定時器沒有及時收到確認,則會重發數據
-
TCP將保持它首部和數據的檢驗和。這是一個端到端的檢驗和,目的是檢測數據在傳輸過程中的任何變化。如果收到段的檢驗和有差錯,TCP將丟棄這個報文段和不確認收到此報文段(希望發端超時并重發)。
-
兩個應用程序通過TCP連接交換8bit字節構成的字節流。TCP不在字節流中插入記錄標識符。我們將這稱為字節流服務(bytestreamservice)。如果一方的應用程序先傳10字節,又傳20字節,再傳50字節,連接的另一方將無法了解發方每次發送了多少字節。只要自己的接收緩存沒有塞滿,TCP 接收方將有多少就收多少。一端將字節流放到TCP連接上,同樣的字節流將出現在TCP連接的另一端。
四次揮手
建立一個連接需要三次握手,而終止一個連接要經過四次揮手,這是由TCP的半關閉(half-close)造成的。具體過程如下所示。
- 某個應用進程首先調用close,稱該端執行“主動關閉”(active close)。該端的TCP于是發送一個FIN分節,表示數據發送完畢。
- 接收到這個FIN的對端執行 “被動關閉”(passive close),這個FIN由TCP確認。
- 注意:FIN的接收也作為一個文件結束符(end-of-file)傳遞給接收端應用進程,放在已排隊等候該應用進程接收的任何其他數據之后,因為,FIN的接收意味著接收端應用進程在相應連接上再無額外數據可接收。
- 一段時間后,接收到這個文件結束符的應用進程將調用close關閉它的套接字。這導致它的TCP也發送一個FIN。
- 接收這個最終FIN的原發送端TCP(即執行主動關閉的那一端)確認這個FIN。 既然每個方向都需要一個FIN和一個ACK,因此通常需要4個分節。
“通常”是指,某些情況下,步驟1的FIN隨數據一起發送,另外,步驟2和步驟3發送的分節都出自執行被動關閉那一端,有可能被合并成一個分節。 在步驟2與步驟3之間,從執行被動關閉一端到執行主動關閉一端流動數據是可能的,這稱為“半關閉”(half-close)。 當一個Unix進程無論自愿地(調用exit或從main函數返回)還是非自愿地(收到一個終止本進程的信號)終止時,所有打開的描述符都被關閉,這也導致仍然打開的任何TCP連接上也發出一個FIN。 無論是客戶還是服務器,任何一端都可以執行主動關閉。通常情況是,客戶執行主動關閉,但是某些協議,例如,HTTP/1.0卻由服務器執行主動關閉。
php中的tcp
php可通過socket函數,swoole擴展,stream流函數進行創建tcp協議的socket,綁定網卡端口,進行tcp服務端/客戶端操作
在php中,我們并不需要了解tcp的握手/揮手,我們只需要知道ip:port能連接/創建 一個tcp服務端/客戶端就行了
使用php的socket,我們可以直接發送字符串,接收的也是字符串,其他一切都是語言,操作系統所需要做的事,
我們只需要處理好字符串的完整性,例如我們使用php做tcp服務端
- 客戶端連接成功后,發送了一個"easyswoole是一個非常好的swoole框架"的字符串
- 而服務端每次只接收9個字節,那第一次獲取只會接收到"easyswool"的殘缺字符串,需要繼續獲取數據
其他
可自行搜索詳細理解