TCP網絡編程開發分爲服務器端和客戶端兩個部分 編程
對於服務器端開發主要流程--相似於 接電話過程服務器
socket()[找到一個能夠通話的手機]----->bind()[插入一個固定號碼]------>listen()-------> accept------->recv()------->send()------>close();網絡
對於客戶端開發主要流程----相似於打電話過程socket
socket()----->connect()------>recv/read/send------>close()函數
對於TCP協議 =創建鏈接就在客戶端connect()與服務器listen之間 創建TCP鏈接(三次握手) server
對於四次揮手 狀態兩個PC之間close狀態隊列
1. Connect()函數:是一個阻塞函數 經過TCp三次握手父服務器創建鏈接內存
客戶端主動鏈接服務器 創建鏈接方式經過TCP三次握手通知Linux內核自動完成TCP 三次握手鍊接 若是鏈接成功爲0 失敗返回值-1資源
通常的狀況下 客戶端的connect函數 默認是阻塞行爲 直到三次握手階段成功爲止。開發
2.服務器端的listen() 函數:不是一個阻塞函數: 功能:將套接字 和 套接字對應隊列的長度告訴Linux內核
他是被動鏈接的 一直監聽來自不一樣客戶端的請求 listen函數只要 做用將socketfd 變成被動的鏈接監聽socket 其中參數backlog做用 設置內核中隊列的長度 。
3.accept() 函數 阻塞:從處於established 狀態的隊列中取出完成的鏈接 當隊列中沒有完成鏈接時候 會造成阻塞,直到取出隊列中已完成鏈接的用戶鏈接爲止。
問題一:服務器沒有及時調用accept函數取走完成鏈接的隊列怎麼辦?
服務器的鏈接隊列滿掉後,服務器不會對再對創建新鏈接的syn進行應答,因此客戶端的 connect 就會返回 ETIMEDOUT。但實際上Linux的並非這樣的 當TCP鏈接隊列滿了以後 Linux並不會書中所說的拒絕鏈接,只是會延時鏈接。
2.TCP三次握手機制:三次握手機制保證通訊是雙工,可靠保證 更多經過重傳機制
1.Client 主動向處於listen狀態的服務器發送 SYN_SENT 報文;
2. Server SYN_RECVD以後 分配資源內存同時向client發送 SYN_ACK 確認接受的報文
3.Client 接受到服務器SYN_ACK 本地開闢內存資源 同時回覆Server 發送SYN_ACK+I報文已經接受ACK報文信息 至此TCP鏈接創建起來
3.TCP 四次揮手:
1.客戶端A向服務器發送FIN,用來用來關閉A到serverB的數據傳送
2.服務器B接受到 這個FIN 它發回一個ACK確認報文 確認序列號+1 (客戶端處於FIN_WAIT2)
3.服務器B關閉客戶端A的鏈接發送一個FIN報文 本身進行鏈接關閉
4.客戶端A 接受到server的FIN報文 回覆ACK報文確認 此時客戶端進入TIME_WAT d等待 通過2MLS 沒有收到服務器的ACK確認信息自動進行關閉。
FIN報文 告訴本身 對方沒有數據進行發送 並不能阻止本身發送數據,所以有可能仍是有些數據發生給對方所以在關閉鏈接時候 ACK報文與FIN報文是分開 這也致使關閉時候須要四次揮手
問題一:TIME_WAT 狀態中還須要等待2MS時間後才進行關閉
雖然雙方都贊成關閉鏈接 按理能夠直接回到 CLOSED 狀態,事實上網絡不可靠的 沒法保證服務器可以接受到客戶端的ACK確認消息。有可能讓處於last_ACK 的server 認爲超時重複FIN報文,因此TIME_WAT狀態 做用重發可能丟失的ACK報文