簡單理解Socket
要想理解簡單理解Socket首先得熟悉簡單理解Socket協議族, 簡單理解Socket(Transmission Control Protocol/Internet Protocol)即傳輸控制協議/網間協議,定義了主機如何連接到因特網及資料如何再它們之間傳輸的標準,
從字面意思來看簡單理解Socket是TCP和IP協定的合稱,但實際上簡單理解Socket協定是指因特網整個簡單理解Socket協定族。有別於ISO模型的七個分層,簡單理解Socket協定參考模型把所有的簡單理解Socket系列協定歸類到四個抽象層中
應用層:TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet等等
傳輸層:TCP,UDP
網路層:IP,ICMP,OSPF,EIGRP,IGMP
資料鏈結層:SLIP,CSLIP,PPP,MTU
每一抽象層建立在低層提供在的服務上,並且為高一層提供服務,看起來大概是這樣子的
估計有興趣打開此文的同學都對此有一定了解了,加上我也是一知半解,所以就不詳細解釋,有興趣同學可以上網搜一下資料
在簡單理解Socket協定中兩個因特網主機透過兩個路由器和對應的層連接。各主機上的應用透過一些資料通道互相執行讀取操作
簡單理解Socket
我們知道兩個進程如果需要進行通訊最基本的一個前提能能夠唯一的標示一個進程,在本地進程中我們可以使用PID來唯一標示一個進程,但PID只在本地唯一,網路中的兩個進程PID衝突幾率很大,這時候我們需要另闢它徑了,我們知道IP層的ip位址可以唯一標示主機,而TCP層協定和埠號可以唯一標示主機的一個進程,這樣我們可以利用ip位址+協定+埠號唯一標示網路中的一個進程。
能夠唯一標示網路中的進程後,它們就可以利用簡單理解Socket進行通訊了,什麼是簡單理解Socket呢?我們經常把簡單理解Socket翻譯為套接字,簡單理解Socket是在應用層和傳輸層之間的一個抽象層,它把簡單理解Socket層複雜的操作抽象為幾個簡單的接口供應用層調用已實現進程在網絡中通信。
簡單理解Socket起源於UNIX,在Unix一切皆文件哲學的思想下,簡單理解Socket是一種"打開—讀/寫—關閉"模式的實現,伺服器和客戶端各自維護一個"文件",在建立連線開啟後,可以寫入內容給自己檔案供對方讀取或讀取對方內容,通訊結束時關閉檔案。
簡單理解Socket通訊流程
簡單理解Socket是"開啟—讀/寫—關閉"模式的實現,以使用TCP協定通訊的簡單理解Socket為例,其交互流程大概是這樣子的
伺服器根據地址類型( ipv4,ipv6)、簡單理解Socket類型、協定創建簡單理解Socket
伺服器為簡單理解Socket綁定ip位址和連接埠號碼
伺服器簡單理解Socket監聽連接埠號碼請求,隨時準備接收客戶端發來的連接,這時候伺服器的簡單理解Socket並沒有被打開
客戶端創建簡單理解Socket
客戶端打開簡單理解Socket,根據伺服器ip位址和連接埠號碼試圖連接伺服器簡單理解Socket
伺服器簡單理解Socket接收到客戶端簡單理解Socket請求,被動打開,開始接收客戶端請求,直到客戶端返回連接資訊.這時候簡單理解Socket進入阻塞狀態,所謂阻塞即accept()方法一直到客戶端返回連接訊息後才返回,開始接收下一個客戶端諒解請求
客戶端連接成功,向伺服器發送連接狀態資訊
伺服器accept方法返回,連接成功
客戶端向簡單理解Socket寫入訊息
伺服器讀取訊息
客戶端關閉
伺服器端關閉
三次握手
在簡單理解Socket協定中,TCP協定透過三次握手建立一個可靠的連線
第一次握手:客戶端嘗試連接伺服器,向伺服器發送syn套件(同步序列編號Synchronize Sequence Numbers ),syn=j,客戶端進入SYN_SEND狀態等待伺服器確認
第二次握手:伺服器接收客戶端syn套件並確認(ack=j+1),同時向客戶端發送一個SYN套件(syn=k) ,即SYN+ACK包,此時伺服器進入SYN_RECV狀態
第三次握手:第三次握手:客戶端收到伺服器的SYN+ACK包,向伺服器發送確認包ACK(ack=k+1),此包寄完畢,客戶端和伺服器進入ESTABLISHED狀態,完成三次握手
定睛一看,伺服器簡單理解Socket與客戶端簡單理解Socket建立連線的部分其實就是大名鼎鼎的三次握手
到簡單理解Socket是"打開—讀/寫—關閉"模式的實現,簡單了解一下簡單理解Socket提供了哪些API供應用程序使用,還是以TCP協議為例,看看Unix下的簡單理解Socket API,其它語言都很類似( PHP甚至名字都幾乎一樣),這裡我就簡單解釋一下方法作用和參數,具體使用有興趣同學可以看看博客參考中的鏈接或者上網搜索int 簡單理解Socket(int domain, int type, int protocol);根據指定的位址族、資料型別和協定來分配一個簡單理解Socket的描述字及其所使用的資源。
通常伺服器在啟動的時候都會綁定一個眾所周知的位址(如ip位址+埠號),用於提供服務,客戶就可以透過它來接連伺服器;而客戶端就不用指定,有系統自動分配一個連接埠號碼和自身的ip位址組合。這就是為什麼通常伺服器端在listen之前會調用bind(),而客戶端就不會調用,而是在connect()時由系統隨機產生一個。
int listen(int sockfd, int backlog);
監聽簡單理解Socketsockfd:要監聽的簡單理解Socket描述字, 對應簡單理解Socketet可以排隊的最大連接個數嗎? sockaddr *addr, socklen_t addrlen);連接某個簡單理解Socket
TCP伺服器監聽到客戶端請求之後,呼叫accept()函數取接收請求
:sockfd:伺服器的簡單理解Socket描述字
sockfd:伺服器的簡單理解Socket描述字
addr:客戶端的簡單理解Socket.位址的長度
ssize_t read(int fd, void *buf, size_t count);
讀取簡單理解Socket內容
fd:簡單理解Socket描述字
(int fd, const void *buf, size_t count);
寫入內容,其實就是傳送內容fd:簡單理解Socket描述字buf:緩衝區
count:緩衝區長度
buf:緩衝區
count:緩衝區長度
(int fd);簡單理解Socket標記為以關閉 ,使對應簡單理解Socket描述字的引用計數-1,當引用計數為0的時候,觸發TCP客戶端向伺服器發送終止連線請求。
參考