socket 中listen() 與accept() 的一些理解
阿新 • • 發佈:2019-02-19
在伺服器端,socket()返回的套接字用於監聽(listen)和接受(accept)客戶端的連線請求。這個套接字不能用於與客戶端之間傳送和接收資料。
accept()接受一個客戶端的連線請求,並返回一個新的套接字。所謂“新的”就是說這個套接字與socket()返回的用於監聽和接受客戶端的連線請求的套接字不是同一個套接字。與本次接受的客戶端的通訊是通過在這個新的套接字上傳送和接收資料來完成的。
再次呼叫accept()可以接受下一個客戶端的連線請求,並再次返回一個新的套接字(與socket()返回的套接字、之前accept()返回的套接字都不同的新的套接字)。這個新的套接字用於與這次接受的客戶端之間的通訊。
假設一共有3個客戶端連線到伺服器端。那麼在伺服器端就一共有4個套接字:第1個是socket()返回的、用於監聽的套接字;其餘3個是分別呼叫3次accept()返回的不同的套接字。
如果已經有客戶端連線到伺服器端,不再需要監聽和接受更多的客戶端連線的時候,可以關閉由socket()返回的套接字,而不會影響與客戶端之間的通訊。
當某個客戶端斷開連線、或者是與某個客戶端的通訊完成之後,伺服器端需要關閉用於與該客戶端通訊的套接字。
舉個簡單的例子(以下程式碼只是示範性的,用於說明不同套接字的作用,實際的函式會需要更多的引數):
/* 建立用於監聽和接受客戶端連線請求的套接字 */
server_sock = socket();
/* 繫結監聽的IP地址和埠 */
bind(server_sock);
/* 開始監聽 */
listen(server_sock);
/**
* 等待客戶端連線請求,在沒有客戶端連線請求到來之前,
* 程式會一直阻塞在這個函式裡。
*/
client_sock = accept(server_sock);
/**
* 已經接受客戶端連線請求,accept()函式建立並返回了一個
* 新的套接字client_sock,用於與客戶端通訊。
* 如果不再需要接受其他客戶端的連線請求,可以關閉監聽
* 套接字了。
*/
close(server_sock);
/* 傳送資料到客戶端 */
send(client_sock, data);
/* 從客戶端接收資料 */
recv(client_sock, data);
/* 通訊結束,關閉與客戶端通訊的套接字 */
close(client_sock);