什麼是socket?
Socket 是在應用層和傳輸層之間的一個抽象層,它把TCP/IP 層複雜的操作抽象化為幾個簡單的接口,供應用層調用實現進程在網路中的通信。 Socket 起源於UNIX,在UNIX 一切皆文件的思想下,進程間通訊就被冠名為文件描述符(file descriptor),Socket 是一種「開啟—讀/寫—關閉」模式的實現,伺服器與客戶端各自維護一個“文件”,在建立連接打開後,可以向文件寫入內容供對方讀取或讀取對方內容,通訊結束時關閉文件。
如圖為Socket所在位置:
#Socket 通訊流程
Socket 保證了不同電腦之間的通信,也就是網路通信。對於網站,通訊模型是伺服器與客戶端之間的通訊。兩端都建立了一個 Socket 對象,然後透過 Socket 對象對資料進行傳輸。通常伺服器處於一個無限循環,等待客戶端的連線。
相關學習影片教學分享:php影片教學
下圖是面向連線的TCP 時序圖:
客戶端過程:
客戶端的過程比較簡單,創建Socket,連接伺服器,將Socket 與遠端主機連接(注意:只有TCP 才有「連接」的概念,一些Socket 例如UDP、ICMP 和ARP 沒有「連接」的概念),發送數據,讀取回應數據,直到數據交換完畢,關閉連接,結束TCP 對話。
這裡也可用 send() 方法:不同在於 sendall() 在返回前會嘗試傳送所有數據,並且成功時回傳None,而 send()則回傳的位元組數量,失敗時都拋出異常。
服務端過程:
咱再來聊聊服務端的過程,服務端先初始化Socket,建立串流套接字,與本機位址及連接埠進行綁定,然後通知TCP,準備好接收連接,呼叫 accept() 阻塞,等待來自客戶端的連接。如果這時客戶端與伺服器建立了連接,客戶端發送資料請求,伺服器接收請求並處理請求,然後把回應資料傳送給客戶端,客戶端讀取數據,直到資料交換完畢。最後關閉連接,交互結束。
當呼叫 accept() 時,Socket 會進入waiting狀態。客戶端請求連線時,方法建立連線並返回伺服器。 accept() 傳回一個含有兩個元素的元組 (conn, addr)。第一個元素 conn 是新的 Socket 對象,伺服器必須透過它與客戶端通訊;第二個元素 addr 是客戶端的 IP 位址及連接埠。 data = conn.recv(1024)
接下來是處理階段,伺服器和用戶端透過 send() 和 recv() 通訊(傳送資料)。
伺服器呼叫 send(),並以字串形式傳送訊息,send() 傳回已傳送的字元數。
伺服器呼叫 recv() 從客戶端接收訊息。當呼叫 recv() 時,伺服器必須指定一個整數,它對應於可透過本次方法呼叫來接收的最大資料量。 recv() 在接收資料時會進入blocked狀態,最後回傳一個字串,用它表示收到的資料。如果發送的資料量超過了 recv() 所允許的,則資料會被截斷。多餘的資料將緩衝於接收端,以後呼叫 recv() 時,會繼續讀取剩餘的位元組,如果有多餘的資料會從緩衝區刪除(以及自上次呼叫 recv() 以來,客戶端可能發送的其它任何數據)。傳輸結束,伺服器呼叫 Socket 的 close() 關閉連線。
從 TCP 連線的視角看 Socket 流程:
TCP 三次握手的 Socket 流程:
1、伺服器呼叫 socket()、bind()、listen() 完成初始化後,呼叫 accept() 阻塞等待;
2、客戶端Socket 物件呼叫 connect() 傳送了一個給伺服器給伺服器SYN 並阻塞;
3、伺服器完成了第一次握手,即發送SYN 和ACK 應答;
4、客戶端收到服務端發送的應答之後,從 connect()傳回,再傳送一個ACK 給伺服器;
5、伺服器Socket 物件接收客戶端第三次握手ACK 確認,此時服務端從 accept() 傳回,建立連線。
接下來就是兩個端的連接物件互相收發資料。
TCP 四次揮手的Socket 過程:
1、某個應用程式呼叫 close() 主動關閉,傳送一個FIN;
2、另一端接收到FIN 後被動執行關閉,並發送ACK 確認;
3、之後被動執行關閉的應用程序呼叫 close() 關閉Socket,並也發送一個FIN;
4、接收到這個FIN 的一端向另一端ACK 確認。
總結:
上面的程式碼簡單地示範了 Socket 的基本函數使用,其實不管有多複雜的網路程序,這些基本函數都會用到。上面的服務端程式碼只有處理完一個客戶端請求才會去處理下一個客戶端的請求,這樣的伺服器處理能力很弱,而實際中伺服器都需要有並發處理能力,為了達到並發處理,伺服器就需要fork一個新的行程或執行緒去處理請求。
相關文章教學推薦:php教學
#以上是如何理解php socket的詳細內容。更多資訊請關注PHP中文網其他相關文章!