如何理解php socket

2020-07-16 10:06:33

下圖是面向連線的 TCP 時序圖:

217bc12ea0c309c4c8bf8abc25b4551.png

用戶端過程:

用戶端的過程比較簡單,建立 Socket,連線伺服器,將 Socket 與遠端主機連線(注意:只有 TCP 才有「連線」的概念,一些 Socket 比如 UDP、ICMP 和 ARP 沒有「連線」的概念),傳送資料,讀取響應資料,直到資料交換完畢,關閉連線,結束 TCP 對話。

24d5dd165c0df075eb50d90b9d5da8a.png

這裡也可用 send() 方法:不同在於 sendall() 在返回前會嘗試傳送所有資料,並且成功時返回 None,而 send()則返回傳送的位元組數量,失敗時都丟擲異常。

伺服器端過程:

咱再來聊聊伺服器端的過程,伺服器端先初始化 Socket,建立流式通訊端,與本機地址及埠進行系結,然後通知 TCP,準備好接收連線,呼叫 accept() 阻塞,等待來自用戶端的連線。如果這時用戶端與伺服器建立了連線,用戶端傳送資料請求,伺服器接收請求併處理請求,然後把響應資料傳送給用戶端,用戶端讀取資料,直到資料交換完畢。最後關閉連線,互動結束。

892e514b2debad63c61861435929835.png

呼叫 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 過程:

d18552b1bc79160dc04e0e95d344f02.png

1、伺服器呼叫 socket()、bind()、listen() 完成初始化後,呼叫 accept() 阻塞等待;

2、用戶端 Socket 物件呼叫 connect() 向伺服器傳送了一個 SYN 並阻塞;

3、伺服器完成了第一次握手,即傳送 SYN 和 ACK 應答;

4、用戶端收到伺服器端傳送的應答之後,從 connect() 返回,再傳送一個 ACK 給伺服器;

5、伺服器 Socket 物件接收用戶端第三次握手 ACK 確認,此時伺服器端從 accept() 返回,建立連線。

接下來就是兩個端的連線物件互相收發資料。

TCP 四次揮手的 Socket 過程:

2a6803eb2e68594b86abdba2d69447b.png

1、某個應用進程呼叫 close() 主動關閉,傳送一個 FIN;

2、另一端接收到 FIN 後被動執行關閉,並行送 ACK 確認;

3、之後被動執行關閉的應用進程呼叫 close() 關閉 Socket,並也傳送一個 FIN;

4、接收到這個 FIN 的一端向另一端 ACK 確認。

總結:

上面的程式碼簡單地演示了 Socket 的基本函數使用,其實不管有多複雜的網路程式,這些基本函數都會用到。上面的伺服器端程式碼只有處理完一個用戶端請求才會去處理下一個用戶端的請求,這樣的伺服器處理能力很弱,而實際中伺服器都需要有並行處理能力,為了達到併行處理,伺服器就需要 fork 一個新的進程或者執行緒去處理請求。

相關文章教學推薦:php教學

以上就是如何理解php socket的詳細內容,更多請關注TW511.COM其它相關文章!