PHP中如何使用socket進行通訊?
阿新 • • 發佈:2019-01-24
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連線
?>
php E:\xampp\htdocs\demo\socket_client.php
就可以看到客戶端與伺服器端進行通訊的結果。
最後,推薦使用Workerman 來實現 socket 通訊。(詳情可參考 Workerman官網)
Workerman 是一款純 PHP 開發的開源高效能的PHP
Socket伺服器框架。被廣泛的用於手機app、手遊服務端、網路遊戲伺服器、聊天室伺服器、硬體通訊伺服器、智慧家居、車聯網、物聯網等領域的開發。 支援TCP長連線,支援Websocket、HTTP等協議,支援自定義協議。基於workerman,開發者可以更專注於業務邏輯開發,不必再為 PHP Socket 底層開發而煩惱。