上一篇文章扼要的引见了一下http协定,此次再引见一下WebSocket协定,两者之间有很大的区分,WebSocket协定是 HTML5 最先供应的一种在单个 TCP 衔接上举行全双工通讯的协定。
简朴的明白一下什么是双工通讯协定,之前有讲过http协定只能客户端向服务端提议要求,是单向的运用层协定。而双工通讯协定,不仅客户端能向服务端提议要求,服务端也能够主动推送信息给客户端。
目标:即时通讯,替换轮询
WebSocket 协定在2008年降生,2011年成为国际标准。一切浏览器都已支撑了。
比拟于http协定,websoket协定给我们带来了极大的轻易,举个例子:
之前,我们在做音讯关照的时刻,须要设置定时器,频仍的向背景提议异步ajax要求完成长轮询,猎取最新的数据,如许效力异常低,异常浪费资源,由于不断的提议http要求,不断的与服务端竖立衔接,或许http链接一直翻开。
而如今有了websocket,就处理了轮询的题目,websocket只须要竖立一次衔接,就能够坚持久长衔接,比拟轮询不断的竖立衔接,大大的提升了效力,如许只需服务端有数据变化,就能够马上关照前台了。
websocket协定与http协定之间的关联
起首HTTP有 1.1 和 1.0 之说,也就是所谓的 keep-alive ,把多个HTTP要求合并为一个,然则 Websocket 实际上是一个新协定,跟HTTP协定基础没有关联,只是为了兼容现有浏览器的握手范例罢了,也就是说它是HTTP协定上的一种补充,Websocket是借用了HTTP的协定来完成一部分握手。
websocket有以下特性:
- 竖立在 TCP 协定之上,服务器端的完成比较轻易。
- 与 HTTP 协定有着优越的兼容性。默许端口也是80和443,而且握手阶段采纳 HTTP 协定,因而握手时不轻易屏障,能经由过程种种 HTTP
代理服务器。 - 属于长衔接(http协定无状况)
- 双向通讯(http是单向通讯)
- 能够跨域,不受浏览器同源战略的限定(http协定不可跨域)
- 数据格式比较轻量,机能开支小,通讯高效
- 能够发送文本,也能够发送二进制数据。
- 协定标识符是ws(假如加密,则为wss),服务器网址就是 URL。如:ws://example.com:80/some/path
websocket协定运用
现在websocket对大部分浏览器有很好的兼容,但关于IE10以下的浏览器没法兼容。为了处理兼容性,Socket.IO就涌现了。
Socket.IO是一个基于Nodejs的,用于及时通讯的一个软件包(包含client端和server端),Socket.IO完全由JavaScript完成。
日常平凡在运用的时刻,能够直接引入socket.io这个库就能够了。前背景都须要援用该库。
下面针对nodejs的服务端怎样运用举个例子:
服务端代码:
const http = require('http');
const fs = require('fs');
const express = require('express');
const io = require('socket.io');
const app = express();
const httpServer = http.createServer(app);
app.use('/', express.static(__dirname + '/www'));
httpServer.listen(8081);
const ioserve = io.listen(httpServer);
let users = [];
ioserve.on('connection', (socket) => {
socket.on('login', (nickname) => {
if (users.indexOf(nickname) > -1) {
socket.emit('nickExisted');
} else {
socket.userIndex = users.length;
socket.nickname = nickname;
users.push(nickname);
socket.emit('loginSuccess');
ioserve.sockets.emit('system', nickname, users.length, 'login');
}
});
socket.on('postMsg', function (msg) {
socket.broadcast.emit('newMsg', socket.nickname, msg);
});
socket.on('img', function (imgData) {
socket.broadcast.emit('newImg', socket.nickname, imgData);
})
socket.on('disconnect', function () {
users.splice(socket.userIndex, 1);
socket.broadcast.emit('system', socket.nickname, users.length, 'logout');
});
})
前台代码
html文件
<body>
<div class="wrapper">
<div class="banner">
<h1>HiChat :)</h1>
<span id="status"></span>
</div>
<div id="historyMsg">
</div>
<div class="controls">
<div class="items">
<input id="colorStyle" type="color" placeHolder='#000' title="font color" />
<input id="emoji" type="button" value="emoji" title="emoji" />
<label for="sendImage" class="imageLable">
<input type="button" value="image" />
<input id="sendImage" type="file" value="image" />
</label>
<input id="clearBtn" type="button" value="clear" title="clear screen" />
</div>
<textarea id="messageInput" placeHolder="enter to send"></textarea>
<input id="sendBtn" type="button" value="SEND">
<div id="emojiWrapper">
</div>
</div>
</div>
<div id="loginWrapper">
<p id="info">connecting to server...</p>
<div id="nickWrapper">
<input type="text" placeHolder="nickname" id="nicknameInput" />
<input type="button" value="OK" id="loginBtn" />
</div>
</div>
<script src="/socket.io/socket.io.js"></script>
<script src="js/hichat.js"></script>
</body>
js文件
; (function () {
function Hichart() {
this.socket = null;
}
Hichart.prototype = {
init: function () {
var that = this;
this.socket = io.connect();
this.socket.on('connect', function () {
document.getElementById('info').textContent = 'get yourself a nickname :)';
document.getElementById('nickWrapper').style.display = 'block';
document.getElementById('nicknameInput').focus();
that.login();
that.postMsg();
that.uploadImg();
});
this.socket.on('nickExisted', function () {
document.getElementById('info').textContent = '!nickname is taken, choose another pls';
});
this.socket.on('loginSuccess', function () {
document.title = 'hichat | ' + document.getElementById('nicknameInput').value;
document.getElementById('loginWrapper').style.display = 'none';//隐蔽遮罩层显谈天界面
document.getElementById('messageInput').focus();//让音讯输入框取得核心
});
this.socket.on('system', function (nickname, userCount, type) {
var msg = nickname + (type === 'login' ? ' joined' : ' left');
that.displayNewMsg('system ', msg, 'red');
document.getElementById('status').textContent = userCount + (userCount > 1 ? ' users' : ' user') + ' online';
});
this.socket.on('newMsg', function (nickname, msg) {
that.displayNewMsg(nickname, msg);
});
this.socket.on('newImg', function (nickname, newImg) {
that.displayImage(nickname, newImg);
});
},
login: function () {
var that = this;
document.getElementById('loginBtn').addEventListener('click', function () {
var nickname = document.getElementById('nicknameInput').value;
if (nickname.trim().length) {
that.socket.emit('login', nickname);
} else {
document.getElementById('nicknameInput').focus();
}
}, false)
},
displayNewMsg: function (user, msg, color) {
var container = document.getElementById('historyMsg');
var msgToDisplay = document.createElement('p');
var data = new Date().toTimeString().substr(0, 8);
msgToDisplay.style.color = color || '#000';
msgToDisplay.innerHTML = user + '<span class="timespan">(' + data + '): </span>' + msg;
container.appendChild(msgToDisplay);
container.scrollTop = container.scrollHeight;
},
displayImage: function (user, imgData, color) {
var container = document.getElementById('historyMsg'),
msgToDisplay = document.createElement('p'),
date = new Date().toTimeString().substr(0, 8);
msgToDisplay.style.color = color || '#000';
msgToDisplay.innerHTML = user + '<span class="timespan">(' + date + '): </span> <br/>' + '<a href="' + imgData + '" target="_blank"><img src="' + imgData + '"/></a>';
container.appendChild(msgToDisplay);
container.scrollTop = container.scrollHeight;
},
postMsg: function () {
var that = this;
var sendBtn = document.getElementById('sendBtn');
var messageInput = document.getElementById('messageInput');
sendBtn.addEventListener('click', function () {
var msg = messageInput.value;
if (msg.trim().length != 0) {
messageInput.value = '';
messageInput.focus();
that.socket.emit('postMsg', msg);
that.displayNewMsg('me', msg);
}
});
},
uploadImg: function () {
var that = this;
document.getElementById('sendImage').addEventListener('change', function () {
if (this.files.length) {
var file = this.files[0];
var reader = new FileReader();
if (!reader) {
that.displayNewMsg('system', '!your browser doesn\'t support fileReader', 'red');
this.value = '';
return;
}
reader.onload = function (e) {
this.value = '';
that.socket.emit('img', e.target.result);
that.displayImage('me', e.target.result);
}
reader.readAsDataURL(file);
}
})
}
}
window.onload = function () {
var hichart = new Hichart();
hichart.init();
}
})()
完全demo请检察我的github,地点:https://github.com/jianwenjua…