Websocket只是一個(gè)網(wǎng)絡(luò)通信協(xié)議
就像 http胸懈、ftp等都是網(wǎng)絡(luò)通信的協(xié)議扬舒;不要多想;
相對(duì)于HTTP這種非持久的協(xié)議來說抬闯,Websocket是一個(gè)持久化網(wǎng)絡(luò)通信的協(xié)議;
WebSocket和HTTP的關(guān)系
WebSocket和HTTP的關(guān)系
有交集关筒,但是并不是全部溶握。
Websocket只是借用了HTTP的一部分協(xié)議來完成一次握手。(HTTP的三次握手蒸播,此處只完成一次)
http和websocket 請(qǐng)求頭對(duì)比:
HTTP:
原來的時(shí)候睡榆,客戶端通過http(騎馬)帶著信請(qǐng)求服務(wù)器,服務(wù)器處理請(qǐng)求(寫回信)袍榆,再次通過http(騎馬)返回胀屿;鏈接斷開;
WebSocket:
客戶端通過http(騎馬)帶著信請(qǐng)求服務(wù)器包雀,但同時(shí)碉纳,攜帶了Upgrade:websocket和Connection:Upgrade(兩根管子),服務(wù)器如果支持WebSocket協(xié)議(有兩根管子的接口),使用Websocket協(xié)議返回可用信息(丟棄馬匹)馏艾,此后信息的傳遞劳曹,均使用這兩個(gè)管子,除非有一方人為的將管子切斷;若服務(wù)器不支持琅摩,客戶端請(qǐng)求鏈接失敗铁孵,返回錯(cuò)誤信息;
http和websocket 響應(yīng)頭對(duì)比:
websocket響應(yīng)頭.jpg](http://upload-images.jianshu.io/upload_images/3776053-7c631bc894a77683.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
websocket和ajax輪詢房资、long poll的區(qū)別
首先是 ajax輪詢 蜕劝,ajax輪詢的原理非常簡單,讓瀏覽器隔個(gè)幾秒就發(fā)送一次請(qǐng)求轰异,詢問服務(wù)器是否有新信息
場景再現(xiàn):
客戶端:啦啦啦岖沛,有沒有新信息(Request)
服務(wù)端:沒有(Response)
客戶端:啦啦啦,有沒有新信息(Request)
服務(wù)端:沒有搭独。婴削。(Response)
客戶端:啦啦啦,有沒有新信息(Request)
服務(wù)端:你好煩啊牙肝,沒有啊唉俗。。(Response)
客戶端:啦啦啦配椭,有沒有新消息(Request)
服務(wù)端:好啦好啦虫溜,有啦給你。(Response)
客戶端:啦啦啦股缸,有沒有新消息(Request)
服務(wù)端:衡楞。。敦姻。沒瘾境。歧杏。。寄雀。沒得滤。。沒有
long poll 其實(shí)原理跟 ajax輪詢 差不多盒犹,都是采用輪詢的方式,不在論述懂更;
從上面可以看出,輪詢其實(shí)就是在不斷地建立HTTP連接急膀,然后等待服務(wù)端處理沮协,可以體現(xiàn)HTTP協(xié)議的另外一個(gè)特點(diǎn),被動(dòng)性卓嫂。同時(shí)慷暂,http的每一次請(qǐng)求與響應(yīng)結(jié)束后,服務(wù)器將客戶端信息全部丟棄晨雳,下次請(qǐng)求行瑞,必須攜帶身份信息(cookie),無狀態(tài)性餐禁;
Websocket的出現(xiàn)血久,干凈利落的解決了這些問題;
所以上面的情景可以做如下修改帮非。
客戶端:啦啦啦氧吐,我要建立Websocket協(xié)議,需要的服務(wù):chat末盔,Websocket協(xié)議版本:17(HTTP Request)
服務(wù)端:ok筑舅,確認(rèn),已升級(jí)為Websocket協(xié)議(HTTP Protocols Switched)
客戶端:麻煩你有信息的時(shí)候推送給我噢陨舱。翠拣。
服務(wù)端:ok,有的時(shí)候會(huì)告訴你的隅忿。
客戶端:balab開始斗圖alabala
服務(wù)端:你好啊ala
客戶端:流鼻血了心剥,我擦……
服務(wù)端:哈哈布爾教育牛啊哈哈哈哈
服務(wù)端:笑死我了哈哈
Swoole
但是,為了用PHP配合HTML5完成一次WebSocket請(qǐng)求和響應(yīng)背桐,哥走過千山萬水,在密林深處蝉揍,發(fā)現(xiàn)了Swoole : http://www.swoole.com/;
PHP語言的異步链峭、并行、高性能網(wǎng)絡(luò)通信框架又沾,使用純C語言編寫弊仪,提供了PHP語言的異步多線程服務(wù)器熙卡,異步TCP/UDP網(wǎng)絡(luò)客戶端,異步MySQL励饵,數(shù)據(jù)庫連接池驳癌,AsyncTask,消息隊(duì)列役听,毫秒定時(shí)器颓鲜,異步文件讀寫,異步DNS查詢典予。
支持的服務(wù):
HttpServer
WebSocket Server
TCP Server
TCP Client
Async-IO(異步)
Task(定時(shí)任務(wù))
環(huán)境依賴:
僅支持Linux甜滨,F(xiàn)reeBSD,MacOS瘤袖,3類操作系統(tǒng)
Linux內(nèi)核版本2.3.32以上
PHP5.3.10以上版本
gcc4.4以上版本或者clang
cmake2.4+衣摩,編譯為libswoole.so作為C/C++庫時(shí)需要使用cmake
安裝:
必須保證系統(tǒng)中有以下這些軟件:
php-5.3.10 或更高版本
gcc-4.4 或更高版本
make
autoconf
Swoole是作為PHP擴(kuò)展來運(yùn)行的
安裝(root權(quán)限):
cd swoole
phpize
./configure
make
sudo make install
配置php.ini
extension=swoole.so
想研究Swoole的同學(xué),自己去看手冊(雖然寫的不好捂敌,但是還是能看懂的)
做一個(gè)聊天室
服務(wù)器端:socket.php
//創(chuàng)建websocket服務(wù)器對(duì)象艾扮,監(jiān)聽0.0.0.0:9502端口
$ws = new swoole_websocket_server("0.0.0.0", 9502);
//監(jiān)聽WebSocket連接打開事件
$ws->on('open', function ($ws, $request) {
$fd[] = $request->fd;
$GLOBALS['fd'][] = $fd;
//$ws->push($request->fd, "hello, welcome\n");
});
//監(jiān)聽WebSocket消息事件
$ws->on('message', function ($ws, $frame) {
$msg = 'from'.$frame->fd.":{$frame->data}\n";
//var_dump($GLOBALS['fd']);
//exit;
foreach($GLOBALS['fd'] as $aa){
foreach($aa as $i){
$ws->push($i,$msg);
}
}
// $ws->push($frame->fd, "server: {$frame->data}");
// $ws->push($frame->fd, "server: {$frame->data}");
});
//監(jiān)聽WebSocket連接關(guān)閉事件
$ws->on('close', function ($ws, $fd) {
echo "client-{$fd} is closed\n";
});
$ws->start();
客戶端:Socket.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="msg"></div>
<input type="text" id="text">
<input type="submit" value="發(fā)送數(shù)據(jù)" onclick="song()">
</body>
<script>
var msg = document.getElementById("msg");
var wsServer = 'ws://192.168.1.253:9502';
//調(diào)用websocket對(duì)象建立連接:
//參數(shù):ws/wss(加密)://ip:port (字符串)
var websocket = new WebSocket(wsServer);
//onopen監(jiān)聽連接打開
websocket.onopen = function (evt) {
//websocket.readyState 屬性:
/*
CONNECTING 0 The connection is not yet open.
OPEN 1 The connection is open and ready to communicate.
CLOSING 2 The connection is in the process of closing.
CLOSED 3 The connection is closed or couldn't be opened.
*/
msg.innerHTML = websocket.readyState;
};
function song(){
var text = document.getElementById('text').value;
document.getElementById('text').value = '';
//向服務(wù)器發(fā)送數(shù)據(jù)
websocket.send(text);
}
//監(jiān)聽連接關(guān)閉
// websocket.onclose = function (evt) {
// console.log("Disconnected");
// };
//onmessage 監(jiān)聽服務(wù)器數(shù)據(jù)推送
websocket.onmessage = function (evt) {
msg.innerHTML += evt.data +'<br>';
// console.log('Retrieved data from server: ' + evt.data);
};
//監(jiān)聽連接錯(cuò)誤信息
// websocket.onerror = function (evt, e) {
// console.log('Error occured: ' + evt.data);
// };
</script>
</html>
websocket API 手冊:
https://developer.mozilla.org/en-US/docs/Web/API/WebSocket