WebSocket网络通讯协议

上一篇文章简要的介绍了一下http协议,此次再介绍一下WebSocket协议,二者之间有很大的区别,WebSocket协议是 HTML5 开始提供的一种在单个 TCP 链接上进行全双工通信的协议。html

简单的理解一下什么是双工通信协议,以前有讲过http协议只能客户端向服务端发起请求,是单向的应用层协议。而双工通信协议,不只客户端能向服务端发起请求,服务端也能够主动推送信息给客户端。node

目的:即时通信,替代轮询

WebSocket 协议在2008年诞生,2011年成为国际标准。全部浏览器都已经支持了。ios

相比于http协议,websoket协议给咱们带来了极大的方便,举个例子:git

以前,咱们在作消息通知的时候,须要设置定时器,频繁的向后台发起异步ajax请求实现长轮询,获取最新的数据,这样效率很是低,很是浪费资源,由于不停的发起http请求,不停的与服务端创建链接,或者http连接始终打开。
而如今有了websocket,就解决了轮询的问题,websocket只须要创建一次链接,就能够保持长久链接,相比轮询不停的创建链接,大大的提高了效率,这样只要服务端有数据变化,就能够当即通知前台了。github

websocket协议与http协议之间的关系

首先HTTP有 1.1 和 1.0 之说,也就是所谓的 keep-alive ,把多个HTTP请求合并为一个,可是 Websocket 实际上是一个新协议,跟HTTP协议基本没有关系,只是为了兼容现有浏览器的握手规范而已,也就是说它是HTTP协议上的一种补充,Websocket是借用了HTTP的协议来完成一部分握手。web

websocket有如下特色:ajax

  • 创建在 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这个库就能够了。先后台都须要引用该库。express

下面针对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...

相关文章
相关标签/搜索