一、WebSocket

1.什麼是WebSocket?

WebSocket協議是基於TCP的一種新的網路協議。它實現了瀏覽器與伺服器全雙工(全雙工(Full Duplex)是通訊傳輸的一個術語。通信允許數據在兩個方向上同時傳輸,它在能力上相當於兩個單工通信方式的結合。全雙工指可以同時(瞬時)進行信號的雙向傳輸(A→B且B→A)。指A→B的同時B→A,是瞬時同步的)。

最大的特點就是:允許伺服器主動發送信息給客戶端。

2.為什麼要用WebSocket?

因為HTTP的通信只能由客戶端發起。

3.關於同步/非同步、阻塞/非阻塞的故事

1.同步阻塞:小明一直盯著下載進度條,到 100% 的時候就完成。

同步體現在:等待下載完成通知;

阻塞體現在:等待下載完成通知過程中,不能做其他任務處理;

2.同步非阻塞:小明提交下載任務後就去幹別的,每過一段時間就去瞄一眼進度條,看到 100% 就完成。

同步體現在:等待下載完成通知;

非阻塞體現在:等待下載完成通知過程中,去幹別的任務了,只是時不時會瞄一眼進度條;(小明必須要在兩個任務間切換,關注下載進度)

3.非同步阻塞:小明換了個有下載完成通知功能的軟體,下載完成就「叮」一聲。不過小明仍然一直等待「叮」的聲音(看起來很傻)。

非同步體現在:下載完成「叮」一聲通知;

阻塞體現在:等待下載完成「叮」一聲通知過程中,不能做其他任務處理;

4.非同步非阻塞:仍然是那個會「叮」一聲的下載軟體,小明提交下載任務後就去幹別的,聽到「叮」的一聲就知道完成了。

非同步體現在:下載完成「叮」一聲通知;

非阻塞體現在:等待下載完成「叮」一聲通知過程中,去幹別的任務了,只需要接收「叮」聲通知即可;(軟體處理下載任務,小明處理其他任務,不需關注進度,只需接收軟體「叮」聲通知即可)

4.Web Socket服務端代碼

<?php
//ws_server.php Web Socket服務端
//內置的WebSocket伺服器支持,通過幾行PHP代碼就可以寫出一個非同步非阻塞多進程的WebSocket伺服器。

$server = new swoole_websocket_server("0.0.0.0", 9506);//監聽本機所有IP的9506埠

//$server->set([]);//運行時參數

//監聽Web Socket連接打開事件
$server->on(open, function (swoole_websocket_server $server, $request) {
echo "我已經和客戶端:{$request->fd} 建立了握手連接
";
});

//監聽Web Socket消息事件
$server->on(message, function (swoole_websocket_server $server, $frame) {
echo "收到客戶端 {$frame->fd} 說:{$frame->data}。opcode:{$frame->opcode},fin:{$frame->finish},並給客戶端回了話
";
$server->push($frame->fd, WebServer說客戶端發來的數據是:.$frame->data);
});

$server->on(close, function ($ser, $fd) {
echo "client {$fd} closed
";
});

$server->start();

5.Web Socket模擬客戶端

<!--ws_client.html-->

<h1>模擬Web Socket客戶端</h1>
<script>
var wsUrl = "ws://192.168.31.212:9506";
var webSocket = new WebSocket(wsUrl);

//實例化JavaScript連接事件
webSocket.onopen = function(evt){
webSocket.send("JavaScript正在向服務端發送數據");
console.log("連接WebSocket成功!");
}

//實例化onmessage
webSocket.onmessage = function(evt){
console.log("伺服器返回的數據:" + evt.data);
}

//實例化onclose事件
webSocket.onclose = function(evt){
console.log("Web Socket連接關閉");
}

//實例化onerror事件
webSocket.onerror = function(evt,e){
console.log("好像有些錯誤:" + evt.data);
}
</script>

6.運行代碼

運行以上代碼需要開啟兩個服務:
1)php http_server.php 啟動HTTP服務,用來提供對靜態頁面的訪問(忘了?可以回顧上篇筆記)
2)php ws_server.php 啟動WebSocket服務。

7.運行結果

瀏覽器:

※連接成功後客戶端會發送數據給服務端,從而出發服務端的message事件,並返回消息給客戶端。

服務端:

用瀏覽器多建立一些socket連接

8.合併ws_server.php、http_server.php服務端代碼

<?php
//ws_server.php Web Socket服務端
//內置的WebSocket伺服器支持,通過幾行PHP代碼就可以寫出一個非同步非阻塞多進程的WebSocket伺服器。

$server = new swoole_websocket_server("0.0.0.0", 9506);//監聽本機所有IP的9506埠

$server->set([
enable_static_handler => true,
document_root => /home/swoole/static,//彷彿看到了Nginx的影子
]);

//監聽Web Socket連接打開事件
$server->on(open, function (swoole_websocket_server $server, $request) {
echo "我已經和客戶端:{$request->fd} 建立了握手連接
";
});

//監聽Web Socket消息事件
$server->on(message, function (swoole_websocket_server $server, $frame) {
echo "收到客戶端 {$frame->fd} 說:{$frame->data}。opcode:{$frame->opcode},fin:{$frame->finish},並給客戶端回了話
";
$server->push($frame->fd, WebServer說客戶端發來的數據是:.$frame->data);
});

$server->on(close, function ($ser, $fd) {
echo "client {$fd} closed
";
});

$server->start();

把提供HTTP服務的http_server.php腳本中的這段代碼合併過來:
$server->set([
enable_static_handler => true,
document_root => /home/swoole/static,//彷彿看到了Nginx的影子
]);

仔細觀察WebSocket的網路請求,是不是與HTTP不同


推薦閱讀:
相關文章