Socket簡介
咱們都知道,使用TCP協議進行包傳輸的過程都須要使用三次握手創建鏈接,交互完又得四次揮手斷開鏈接.對於一個交互頻繁的兩端來講,若是每次發送包都得三次握手、四次揮手這無疑大大下降了發送的效率。node
Socket就很好的解決了上述的問題,它是基於傳輸層TCP、UDP協議的Socket編程。socket編程進行的是端到端的傳輸,中間通過多少個局域網、路由都不關它的事。所以咱們能設置的參數只要傳輸和網絡層linux
使用Socket時須要設置的參數.如使用的是ipv4仍是ipv6協議,用的是TCP仍是UDP,若是用的是TCP協議,則類型爲SOCK_Stream,上節講過傳輸層使用TCP協議時使用流發送到網絡IP層,IP層加上本身的頭變成一個包發送給上一層(MAC層)。UDP的類型是包的方式,爲SOCK_DGRAM編程
基於TCP協議的Socket程序函數調用過程
TCP服務端要先監聽一個端口,通常是先調用bind函數,給這個Socket賦予IP和端口。再調用listen函數讓其處於監聽狀態數組
在內核中.爲每一個Socket維護兩個隊列,一個是已經完成三次握手創建鏈接的隊列,處於establish狀態。另外一個是還沒徹底創建鏈接正在三次握手中的,處於syn_rcvd。緩存
接下來,服務端調用accept函數獲取完成的鏈接進行處理(若是還沒完成鏈接則繼續等待)網絡
客戶端調用connect發起鏈接指明目標IP和端口.而後開始三次握手,內核會給客戶端分配一個臨時的端口。一旦握手成功,服務端的accept就會返回另外一個Socket。在這裏監聽的Socket和真正用來傳輸數據的Socket是兩個,一個叫監聽Socket一個叫作已鏈接Socket數據結構
鏈接創建成功後,雙方就能夠進行read、write以下圖socket
內核中的Socket
說TCP的Socket是一個文件流,確實是這麼一回事。函數
在linux內核中,Socket就是一個文件,那對應的也就有文件描述符(若是對文件及文件描述符這一律念不夠熟悉的,建議先入門操做系統原理或者百度一下先)。socket的read、write都是經過文件描述符來進行。spa
每一個進程都有一個數據結構task_struct,裏面指向一個文件描述符數組,來列出這個進程打開的全部文件的文件描述符。文件描述符是一個整數,是這個數組的下標。
這個數組中的內容是一個指針,指向內核中全部打開文件的列表。既然是一個文件,就會有一個inode,只不過socket對應的inode不像真正的文件系統同樣,保存在硬盤上的,而是在內存中。在這個inode中,指向了socket在內核中的socket結構。
在這個結構裏面,主要的是兩個隊列,一個是發送隊列,一個是接收隊列。在這兩個隊列裏面保存的是一個緩存的sk_buff.這個緩存裏面可以看到完整的包結構。
上圖就是數據結構示意圖.名詞解釋-strcut:結構體,inode:索引節點
基於UDP協議的Socke程序函數調用過程
UDP相對簡單一些,他沒有像TCP那樣複雜的握手揮手。但UDP一樣須要Ip和端口,因此一樣須要調用bind函數。
UDP是沒有維護鏈接狀態的,於是不須要每對鏈接創建一組socket,而是隻要有一個socket,就可以和多個客戶端通訊。也正是由於沒有鏈接狀態,每次通訊的時候,都調用sendto和recvfrm,均可以傳入IP地址和端口。以下圖