Socket通訊原理
在之前的認識TCP/IP協議中瞭解了OSI七層網路模型和TCP/IP四層模型,和TCP/IP中通訊的三次握手、四次揮手,還用Socket寫過聊天室的通訊,但直到昨天才發現自己對Socket的通訊原理的理解是模糊的,所以打算再梳理一下。
OSI七層網路模型和TCP/IP四層模型
先來看下OSI七層網路模型和TCP/IP四層模型有何區別,其實本質上他們是一樣的,都是對一個網路通訊過程的分層模型,只是分層時候側重點有所不同。
我們知道TCP/IP協議是網際網路協議(簇)的統稱,對網路通訊制定了一系列相應的規則,是通訊的基礎,它提供點對點的連結機制,將資料應該如何封裝、定址、傳輸、路由以及在目的地如何接收,都加以標準化
二者最大的不同在於OSI是一個理論上的網路通訊模型,而TCP/IP則是實際執行的網路協議。
Socket是什麼?
說了那麼多,開始進入正題吧。下面是TCP/IP的四層模型,但為什麼我們沒有看到Socekt呢?它應該把放在哪一層?
socket是在應用層和傳輸層之間的一個抽象層,socket本質是程式設計介面(API),它把TCP/IP層複雜的操作抽象為幾個簡單的介面供應用層呼叫以實現程序在網路中通訊。TCP/IP只是一個協議棧,必須要具體實現,同時還要提供對外的操作介面(API),這就是Socket介面
JDK的java.net包下有兩個類:Socket和ServerSocket,在Client和Server建立連線成功後,兩端都會產生一個Socket例項,操作這個例項,完成所需的會話,而我們就通過這些API進行網路程式設計,不需要去關心底層的實現了。 Socket連線過程分為三個步驟:伺服器監聽,客戶端請求,連線確認。
Socket的工作原理
我們只是會用Socekt進行通訊的程式設計了,但socket通訊流程究竟是什麼樣的呢?廢話不扯,還是直接上張圖來理解吧。
socket是"開啟—讀/寫—關閉"模式的實現。
先來看看客戶端和伺服器端的實現吧,來分析一下具體步驟!
客戶端:
伺服器端:
1.伺服器端先初始化Socket。( listenfd 從名稱看就是為了要監聽而建立的socket描述符)
那bind 是幹嘛?是為了宣告說我要佔用這個埠了, 你們都別用了。所以2.繫結埠(bind)
接著 3.listen函式才是真正開始對埠監聽了。
接下來是個死迴圈啊,啊啊也對,因為伺服器端需要一直提供服務,只能坐以待命。那這個accept是幹啥的呢?
4.呼叫accept阻塞,等待客戶端來連線我。
為什麼使用了listenfd , 然後返回了一個新的connfd ? 你還記得伺服器要應付很多的客戶端發起的連線, 所以它一定得把各個客戶端區分開,怎麼區分呢? 那只有用一個新的socket來表示, 可以看到後面接受/傳送(寫和讀)訊息的操作都是基於connfd 來做的。 至於之前的listenfd , 它只起到一個大門的作用了, 意思是說,歡迎敲門, 進門之後我將為你生成一個獨一無二的socket描述符!(引子張大胖的Socekt,o((⊙﹏⊙))o.)
這時有個客戶端初始化一個Socket,然後5.該客戶端連線伺服器(connect),連線成功則建立連線。此時伺服器的accept 相當於和客戶端的connect 一起完成了TCP的三次握手 !
連線建立以後6.客戶端傳送傳送資料請求 7.伺服器接收請求並處理,然後迴應資料給客戶端 8.客戶端讀取到的資料,最後關閉連線。 這樣一次完整的互動就結束了。
還有一個問題就是socket指的是 (IP, Port), 現在我已經有了一個listenfd 的socket, 埠是80 然後每次客戶端發起連線還要建立新的connfd, 因為80埠已經被佔用,難道伺服器端會為每個連線都建立新的埠嗎?
其實新建立的connfd 並沒有使用新的埠號,也是用的80, (在實現聊天室的時候,我們只是為每一個客戶端的連線單獨建立一個執行緒去處理,但並沒有為每個連線都建立新的埠。然而這樣處理是有漏洞的,昨晚就被問到了(′д` )…彡…彡,然後我想了下也是,如果客戶端很多,那這樣做伺服器不得崩了才怪,那怎麼解決了?我答了下用執行緒池吧...又扯了)
因為可以這麼理解,這個socket描述符指向一個數據結構, 例如 listenfd 指向的結構是這樣的:
而一旦accept 新的連線, 新的connfd 就會生成, 像下面的表格, 就生成了兩個connfd , 它們倆伺服器端的ip和port都是相同的, 但是客戶端的IP和Port是不同的, 自然就可以區分開來了。
所以socket 得通過五元組(協議, 客戶端IP, 客戶端Port, 伺服器端IP, 伺服器端Port)來確定。
‘我們只是簡單的使用Socket與ServerSocket就完事了,那是因為底層為我們做了這麼多的工作封裝好讓我們站在巨人肩上程式設計的。
昨日感受:仰望星空腳踏實地。站在巨人肩上可以看得更廣更遠&基礎很重要 “會用與明白如何實現這是專業與非專業的區別” 。