websocket
传统的http请求只能是前端发起,后端响应
但是websocket则是前端和后端都可以主动发送消息给另一方
其本质是tcp连接,并且链接建立之后如果前后端都不去断开则可以一直存在
前端使用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发送方法中的事件,而服务端监听的是客户端发送的消息,所以要服务端的自定义监听事件要和客户端发送消息时自定义的事件相对应
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>
<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>