websocket
傳統的http請求隻能是前端發起,後端響應
但是websocket則是前端和後端都可以主動發送消息給另一方
其本質是tcp連接配接,并且連結建立之後如果前後端都不去斷開則可以一直存在
http://www.websocket.org/
前端使用js實作一個websocket小demo
ws://echo.websocket.org/是官方的一個位址,你發送什麼就傳回什麼
<html>
<head>
<meta charset="utf-8"/>
<title>websocket</title>
</head>
<body>
<h1>Echo test</h1>
<input id="sendTxt" type="text"/>
<button id="sendBtn">發送</button>
<div id="recv"></div>
<script type="text/javascript">
var websocket = new WebSocket("ws://echo.websocket.org/");
websocket.onopen = function(){
console.log('websocket open');
document.getElementById('recv').innerHTML = 'Connected';
}
websocket.onclose = function(){
console.log('websocket close');
}
websocket.onmessage = function(event){
console.log(event.data);
document.getElementById('recv').innerHTML = event.data;
}
document.getElementById('sendBtn').onclick = function(){
var txt = document.getElementById('sendTxt').value;
websocket.send(txt);
}
</script>
</body>
</html>
調試的時候可以看chrome背景觀察消息的發送
用nodejs實作一個websocket server
這裡隻是個demo,其實就是寫的js隻不過是用nodejs運作起來了,nodejs大家自行百度安裝,配好環境變量
然後安裝websocket的依賴包
npm install nodejs-websocket
大家可以觀看guthub上nodejs的websocket demo
https://github.com/sitegui/nodejs-websocket
js小demo如下
用node運作,我這裡用的是win10的新版cmd也就是power shell
node .\websocket.js
var ws = require("nodejs-websocket")
var port = 8001
// Scream server example: "hi" -> "HI!!!"
var server = ws.createServer(function (conn) {
console.log("New connection")
conn.on("text", function (str) {
console.log("Received "+str)
conn.sendText(str.toUpperCase()+"!!!")
})
conn.on("close", function (code, reason) {
console.log("Connection closed")
})
conn.on("error",function(err){
console.log('handler error')
console.log(err)
})
}).listen(port)
console.log('websocket server listening on port ' + port)
對上面的小demo稍微優化一波,建構一個簡陋聊天室
html如下
<html>
<head>
<meta charset="utf-8"/>
<title>websocket</title>
</head>
<body>
<h1>Chat Room</h1>
<input id="sendTxt" type="text"/>
<button id="sendBtn">發送</button>
<script type="text/javascript">
var websocket = new WebSocket("ws://localhost:8001");
function showMessage(str,type){
var div = document.createElement('div');
if('enter' == type){
div.style.color = 'blue';
}else if ('leave' == type){
div.style.color = 'red';
}
div.innerHTML = str;
document.body.appendChild(div);
}
websocket.onopen = function(){
console.log('websocket open');
document.getElementById('sendBtn').onclick = function(){
var txt = document.getElementById('sendTxt').value;
if(txt){
websocket.send(txt);
}
}
}
websocket.onclose = function(){
console.log('websocket close');
}
websocket.onmessage = function(event){
console.log(event.data);
var mes = JSON.parse(event.data)
showMessage(mes.data,mes.type);
}
</script>
</body>
</html>
js如下
var ws = require("nodejs-websocket")
var port = 8001
var clientCount = 0
// Scream server example: "hi" -> "HI!!!"
var server = ws.createServer(function (conn) {
console.log("New connection")
clientCount ++
conn.nickName = 'user' + clientCount
var mes = {}
mes.type = 'enter'
mes.data = conn.nickName + ' come in'
breoadCast(JSON.stringify(mes))
conn.on("text", function (str) {
console.log("Received "+str)
var mes = {}
mes.type = 'message'
mes.data = conn.nickName + ' say: ' + str
breoadCast(JSON.stringify(mes))
})
conn.on("close", function (code, reason) {
console.log("Connection closed")
var mes = {}
mes.type = 'leave'
mes.data = conn.nickName + ' left'
breoadCast(JSON.stringify(mes))
})
conn.on("error",function(err){
console.log('handler error')
console.log(err)
})
}).listen(port)
console.log('websocket server listening on port ' + port)
function breoadCast(str){
server.connections.forEach(function(connection){
connection.sendText(str)
})
}
引入soccketio對websocket進行封裝
慣例先上一波socket.io的官網
https://socket.io/docs/#Installing
socket.io的優勢
1-在發送消息的時候直接可以發送對象,不像原生的websocket隻能把對象轉成json字元串後發送
2-可以自定義事件,例如服務端發送消息,在用戶端接收消息,這個事件可以自定義事件名
demo如下
服務端
使用nodejs,socketIo中的io代表了所有連接配接上的連結,廣播的時候直接用io.emit就可以發送消息,不用向之前用原生的websocket需要周遊發送,單獨的function(socket)中的socket就隻是代表是目前的連接配接(單個連接配接)
還有一個就是demo中io.emit(‘enter’,XXXX)這裡的enter就是自定義事件,服務端用了enter,在用戶端也用這個enter事件去接收響應
var app = require('http').createServer();
var io = require("socket.io")(app);
var port = 3000
app.listen(port);
var clientCount = 0
io.on('connection',function(socket){
clientCount ++
socket.nickname = 'user' + clientCount
//io針對所有的連接配接對象,即廣播
//單個socket對象僅針對目前連接配接對象
io.emit('enter',socket.nickname + ' comes in')
socket.on('message', function(str){
io.emit('message',socket.nickname + ' says: ' + str)
})
socket.on('disconnect', function(){
io.emit('leave', socket.nickname + ' left')
})
})
console.log('websocket server listening on port ' + port)
用戶端
使用html+js
這裡的socket.io.js可以自己儲存下來,
也可以直接引用cdn
用戶端這裡定義的enter,message,leave響應事件都是自定義的,目前是和服務端對應的
當然大家可以注意到用戶端響應的都是服務端io.emit方法中,定義的自定義事件,并不是socket.on裡定義的
因為用戶端監聽的是服務端發送的消息,是以監聽就要監聽emit發送方法中的事件,而服務端監聽的是用戶端發送的消息,是以要服務端的自定義監聽事件要和用戶端發送消息時自定義的事件相對應
<html>
<head>
<meta charset="utf-8"/>
<title>websocket</title>
<script src="./socket.io.js"></script>
</head>
<body>
<h1>Chat Room</h1>
<input id="sendTxt" type="text"/>
<button id="sendBtn">發送</button>
<script type="text/javascript">
var socket = io("ws://localhost:3000/");
function showMessage(str,type){
var div = document.createElement('div');
if('enter' == type){
div.style.color = 'blue';
}else if ('leave' == type){
div.style.color = 'red';
}
div.innerHTML = str;
document.body.appendChild(div);
}
document.getElementById('sendBtn').onclick = function(){
var txt = document.getElementById('sendTxt').value;
if(txt){
socket.emit('message',txt);
}
}
socket.on('enter',function(data){
showMessage(data,'enter')
})
socket.on('message',function(data){
showMessage(data,'message')
})
socket.on('leave',function(data){
showMessage(data,'leave')
})
</script>
</body>
</html>