socket即時通訊

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

就可以看到客戶端與伺服器端進行通訊的結果。