webSocket(与http请求区别、请求和返回示例、替代方法:ajax轮询、long poll、Flash、NodeJS实现WebSocket通信代码、原理、WebSocket构造函数详解)

目录

简介

优点

请求示例

请求成功返回示例

替代方法

Ajax 轮询

long poll

Flash

NodeJS实现webSocket(ws模块)

服务端代码

客户端代码

在线网页客户端

运行结果

服务端运行结果

在线网页客户端运行结果

 本地网页客户端运行结果

原理

通信原理

消息转发原理

客户端WebSocket构造函数详解

net

SocketIO

实例

服务端代码

客户端代码

官网


简介

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

http1.1的keep-alive中,在一个HTTP连接中,可以发送多个Request,接收多个Response。但是一个request只能有一个response。而且这个response也是被动的,不能主动发起

而WebSocket允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

优点

websocket具有以下几个方面的优势:

(1)建立在 TCP 协议之上,服务器端的实现比较容易。

(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

(3)数据格式比较轻量,性能开销小,通信高效。

(4)可以发送文本,也可以发送二进制数据。

(5)没有同源限制,客户端可以与任意服务器通信。

(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

请求示例

下面为webSocket的一个请求头信息。

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com

1. Upgrade: websocket、Connection: Upgrade是告诉服务器要升级为webSocket协议而不是http协议。

2.Sec-WebSocket-Key 是一个Base64 encode的值,这个是浏览器随机生成的,告诉服务器唯一的key值。

3.Sec_WebSocket-Protocol 是一个用户定义的字符串,用来区分同URL下,不同的服务所需要的协议。

4.Sec-WebSocket-Version 是告诉服务器所使用的Websocket Draft(协议版本),在最初的时候,Websocket协议还在 Draft 阶段,各种奇奇怪怪的协议都有,而且还有很多期奇奇怪怪不同的东西,什么Firefox和Chrome用的不是一个版本之类的。

请求成功返回示例

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat

1.Sec-WebSocket-Accept 这个则是经过服务器确认,并且加密过后的 Sec-WebSocket-Key。

2.Sec-WebSocket-Protocol 则是表示最终使用的协议。 

替代方法

ajax轮询需要服务器有很快的处理速度和资源long poll 需要有很高的并发,也就是说同时接待客户的能力。Flash兼容性很差。

Ajax 轮询

浏览器隔个几秒就发送一次请求,询问服务器是否有新信息。现在很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。

long poll

采用轮询的方式,不过采取的是阻塞模型(一直打电话,没收到就不挂电话),也就是说,客户端发起连接后,如果没消息,就一直不返回Response给客户端。直到有消息才返回,返回完之后,客户端再次建立连接,周而复始。

 WebSocket 协议能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

Flash

AdobeFlash通过自己的Socket实现完成数据交换,再利用Flash暴露出相应的接口给JavaScript调用,从而达到实时传输目的。此方式比轮询要高效,且因为Flash安装率高,应用场景广泛。然而,移动互联网终端上Flash的支持并不好:IOS系统中无法支持Flash,Android虽然支持Flash但实际的使用效果差强人意,且对移动设备的硬件配置要求较高。2012年Adobe官方宣布不再支持Android4.1+系统,宣告了Flash在移动终端上的死亡。


NodeJS实现webSocket(ws模块)

ws模块是第三方模块,可以用于前端和后端。net模块是nodejs内置模块,用于后端。socket.io也是第三方模块用于兼容非html5的浏览器。

首先通过命令行npm install -s ws安装ws模块

服务端代码

通过node 当前文件名执行。

//导入ws模块
const WebSocket = require('ws');
//获取服务端类
const WebSocketServer =WebSocket.Server
//创建服务端实例
const Server = new WebSocketServer({
    port:9527
})
//监听服务端连接事件
Server.on("connection",client =>{
    console.log('连接成功')
    //监听客户端断开连接事件
    client.on('close',()=>{
        console.log("连接断开")
    })
    //监听客户端错误事件
    client.on('erro',err=>{
        console.log(err)
    })
    //监听客户端发送的消息
    client.on('message',data=>{
        console.log('二进制流数据:',data)
        //二进制流数据通过toString方法转换为字符串
        console.log(data.toString())
        //消息转发器它客户端,Server.clients为所有的client的数组
        Server.clients.forEach(otherClient=>{
            if(client !=otherClient){
                otherClient.send(data.toString())
            }
        })
    })
    //向客户端发送数据
    client.send('你好,客户端~')
})

客户端代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        var url = 'ws://127.0.0.1:9527'
        //创建WebSocket客户端对象
        var ws = new WebSocket(url)
        //连接事件
        ws.onopen = function () {
            console.log('连接事件')
            ws.send('你好,我是本地客户端')
        }
        //关闭连接事件
        ws.onclose = function () {
            console.log('关闭连接事件')
        }
        //连接错误事件
        ws.onerror = function (err) {
            console.log(err)
        }
        //接收消息事件
        ws.onmessage = function (event) {
            console.log(event)
            //event.data为服务器发送的数据
            console.log(event.data)
        }
       
    </script>
</body>

</html>

在线网页客户端

在线websocket测试-online tool-postjson

运行结果

先打开服务端,在打开本地网页客户端,在打开在线网页客户端,在在线网页客户端中发送我是在线网站,结果如下图:

服务端运行结果

在线网页客户端运行结果

 本地网页客户端运行结果

原理

通信原理

nodejs通过ws模块中的Server构造函数创建服务端,打开如下9527端口监听,当有客户端1连接时,便会在服务端中创建一个client1对象,之后通过client1对象和客户端1进行数据传输,当客户端2连接时便会创建client2,以此类推。

消息转发原理

例如客户端1发送消息到服务端,服务端通过Server.clients拿到所有的client对象,并判断和当前的cliet1对象是否相同,如果不同就把服务端接收到的数据用client转发客户端。

客户端WebSocket构造函数详解

WebSocket 教程 - 阮一峰的网络日志

HTML5 WebSocket | 菜鸟教程

net

nodejs内置的websocket模块。

nodejs模块(http、fs、path、url、express、body-parse、cross-env、http-proxy-middleware、nodemon、nvm、nrm)_YF-SOD的博客-CSDN博客

SocketIO

WebSocket是HTML5最新提出的规范,虽然主流浏览器都已经支持,但仍然可能有不兼容的情况,为了兼容所有浏览器,给程序员提供一致的编程体验,SocketIO将WebSocket、AJAX和其它的通信方式全部封装成了统一的通信接口,也就是说,我们在使用SocketIO时,不用担心兼容问题,底层会自动选用最佳的通信方式。因此说,WebSocket是SocketIO的一个子集。

实例

服务端代码

var express = require('express');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
io.on('connection', function (socket) {//客户端连接事件
  socket.on('receive', (msg) => {//监听自定义receive事件,客户端可以通过emit触发,msg为客户端触发时传的数据。
    socket.broadcast.emit('message', msg);//向所有连接的客户端处罚message事件,用于广播消息。
  })
});
server.listen(8082, '127.0.0.1');

客户端代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>socket.io</title>
  <script src="socket.io.js" charset="utf-8"></script>
</head>
<body>
  <h1>gp 交流区</h1>
  <div id="content" name="name" style="overflow-y: scroll; width: 400px; height: 300px; border: solid 1px #000"></div>
  <br />
  <div>
    <input type="text" id="msg" style="width: 200px;">
  </div>
  <button id="submit">提交</button>
  <script>
    var socket = io.connect('http://127.0.0.1:8082');
    const content = document.getElementById('content')
    document.querySelector('#submit')
      .addEventListener('click', function () {
        var msg2 = msg.value
        socket.emit('receive', msg2) // 触发receive事件像服务端传递数据,服务端通过监听相同事件名,获取数据。
        msg.value = ''
        content.innerHTML += msg2 + '<br/>'
      }, false)
      socket.on('message', function(msg){//监听服务端触发的message事件
        content.innerHTML += msg + '<br/>'
      })
  </script>
</body>
</html>

官网

Get started | Socket.IO

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值