1. socket 概述
socket 也稱作套接字,用於描述 IP 地址和埠,是一個通訊鏈的控制代碼,可以用來實現不同計算機之間的通訊。socket 是對 TCP / IP 協議的封裝,它只是提供了一組針對 TCP 或者 UDP 進行程式設計的介面(API)。
socket 利用客戶端 / 伺服器端的模式巧妙地解決了程序之間建立通訊連線的問題。
2. socket 的工作原理
伺服器端先初始化 socket,然後與埠繫結(bind),對埠進行監聽(listen),等待客戶端連線,呼叫accept阻塞。
這時,如果有客戶端初始化一個 socket,然後請求連線伺服器(connect),如果連線成功,客戶端與伺服器端的連線就建立了。客戶端傳送資料請求,伺服器端接收請求並處理請求,然後把響應資料傳送給客戶端,客戶端讀取資料,最後關閉連線,一次互動結束。
3. socket通訊演示
伺服器端的程式碼:
(在 E:\xampp\htdocs\demo 下新建一個php檔案socket_server。php)
<?php
// 設定指令碼最大執行時間,單位為秒,0表示永不超時
set_time_limit(0);
$address = ‘127。0。0。1’;
$port = 10005; // 埠可以是1到65535之間的任何數字,前提是未被佔用
// 建立並返回一個套接字(通訊節點),一個典型的網路連線由 2 個套接字構成,一個執行在伺服器端,另一個執行在客戶端
if( ($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) {
echo “socket_create() failed, reason: ” 。 socket_strerror(socket_last_error()) 。 “\n”;
}
// 繫結socket到具體的主機埠
if (socket_bind($sock, $address, $port) === false) {
echo “socket_bind() failed, reason: ” 。 socket_strerror(socket_last_error($sock)) 。 “\n”;
}
// 監聽socket伺服器上的請求連線,等待接入
if (socket_listen($sock, 5) === false) {
echo “socket_listen() failed, reason: ” 。 socket_strerror(socket_last_error($sock)) 。 “\n”;
}
do {
// 確認客戶端的連線請求,成功後,返回一個新的子socket控制代碼(子執行緒),用於通訊
if (($msgsock = socket_accept($sock)) === false) {
echo “socket_accept() failed, reason: ”。socket_strerror(socket_last_error($sock)) 。 “\n”;
break;
}
$msg = “Welcome to connect ‘$address’”。“\n”;
// 傳送訊息(資料)到客戶端
if (false === socket_write($msgsock, $msg, strlen($msg))){
echo “socket_write() failed, reason: ” 。 socket_strerror(socket_last_error($sock)) 。“\n”;
}
echo “Read client message \n”;
// 讀取客戶端的資料
$receivedData = socket_read($msgsock, 8192);
echo “Received message: ”。$receivedData。“\n”;;
// 將客戶端發來的資料,進行處理,然後再發送資料給客戶端
$responseData = ‘[time:’。date(‘Y-m-d H:i:s’)。‘]’。PHP_EOL。‘[data:’。trim($receivedData)。‘]’;
if (false === socket_write($msgsock, $responseData, strlen($responseData))) {
echo “socket_write() failed, reason: ” 。 socket_strerror(socket_last_error($sock)) 。“\n”;
}
// 關閉連線成功的子socket
socket_close($msgsock);
} while(true);
// 關閉等待接入的socket
socket_close($sock);
?>
伺服器端的程式碼,需要在 cmd 下或者 CLI模式下執行,開啟命令列視窗,輸入如下命令:
php E:\xampp\htdocs\demo\socket_server。php
就可以在伺服器端執行socket服務。
注意:伺服器端的命令列視窗不可關閉。
客戶端的程式碼:
(在 E:\xampp\htdocs\demo 下新建一個php檔案socket_client。php)
<?php
$address = ‘127。0。0。1’;
$service_port = 10005;
// 建立並返回一個套接字(通訊節點)
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
echo “socket_create() failed, reason: ”。socket_strerror(socket_last_error())。“\n”;
}
echo “Attempting to connect to ‘$address’ on port ‘$service_port’。。。”;
// 發起socket連線請求
$result = socket_connect($socket, $address, $service_port);
if($result === false) {
echo “socket_connect() failed, reason: ”。socket_strerror(socket_last_error($socket))。“\n”;
} else {
echo “Connect success。 \n”;
}
$input = “This is a message from client”。“\n”;
// 向socket伺服器傳送訊息
socket_write($socket, $input, strlen($input));
echo “Client send success \n”;
echo “Reading response:\n”;
// 讀取socket伺服器傳送的訊息
while ($out = socket_read($socket, 8192)) {
echo $out;
}
echo PHP_EOL;
socket_close($socket); // 關閉socket連線
?>
客戶端的程式碼,可以在瀏覽器中執行(如:http://demo。com/socket_client。php),也可以在命令列視窗執行,新開啟一個cmd,輸入如下命令:
php E:\xampp\htdocs\demo\socket_client。php
就可以看到客戶端與伺服器端進行通訊的結果。