websocket发送对象,发送websocket请求
WebSocket对象的生成语法
可以使用多种WebSocket对象特性提供关于WebSocket对象的更多信息:readyState、bufferedAmount和protocol。
1. WebSocket对象特性:readyState
WebSocket对象通过只读特性readyState报告其连接状态,你在前面的几节中已经学到了一点相关的知识。这个属性根据连接状态自动变化,并提供关于WebSocket连接的有用信息。
正如WebSocket API所描述的,当WebSocket对象第一次创建时,readyState为0,表示套接字正在连接。了解WebSocket连接的当前状态有助于应用程序的调试,例如,确保在尝试开始向服务器发送请求之前已经打开了WebSocket连接。这一信息对于了解连接的生命周期也很有用。
二WebSocket对象特性:bufferedAmount
设计应用程序时,你可能想要检查发往服务器的缓冲数据量,特别是在客户端应用程序向服务器发送大量数据的时候。尽管调用send()是立即生效的,但是数据在互联网上的传输却不是如此。浏览器将为你的客户端应用程序缓存出站数据,从而使你可以随时调用send(),发送任意数量的数据。然而,如果你想知道数据在网络上传送的速率,WebSocket对象可以告诉你缓存的大小。你可以使用bufferedAmount特性检查已经进入队列,但是尚未发送到服务器的字节数。这个特性报告的值不包括协议组帧开销或者操作系统、网络硬件所进行的缓冲。
三 WebSocket对象特性:protocol
在前面关于WebSocket构造函数的讨论中,我们提到了protocol参数,它让服务器知道客户端理解并可在WebSocket上使用的协议。WebSocket对象的protocol特性提供了另一条关于WebSocket实例的有用信息。客户端和服务器协议协商的结果可以在WebSocket对象上看到。protocol特性包含在打开握手期间WebSocket服务器选择的协议名,换句话说,protocol特性告诉你特定WebSocket上使用的协议。protocol特性在最初的握手完成之前为空,如果服务器没有选择客户端提供的某个协议,该特性保持空值。
WebSocket(基于TCP的全双工通信协议)
WebSocket 是一种在单个 TCP 连接上进行 全双工 通信的协议。
WebSockets 它可以在用户的浏览器和服务器之间打开交互式通信会话。使用此 API ,可以向服务器发送消息并接收事件驱动的响应,而无需通过轮询服务器的方式以获得响应。 WebSocket 对象提供了用于创建和管理 WebSocket 连接,以及可以通过该连接发送和接收数据的API。
websocket
建立连接(创建WebSocket对象):
var Socket =new WebSocket(url, [protocol] );// url:服务器端地址;protocol:可选,指定可接受的子协议。
WebSocket对象提供了两个属性、四个事件、两个方法,分别是:
1.WebSocket.readyState属性:表示连接状态
????0——(连接尚未建立);1——(连接已建立);2——(连接正在关闭);3——(连接已经关闭或连接不能打开)
2.WebSocket.bufferedAmount属性:被send()放入传输队列,还未发出的UTF-8文本字节数
????ws.addEventListener('open',function(event){
????????????ws.send('Hello Server!');
????});
? ? ?ws.onopen =function(){
????????ws.send('Hello Server!');
????}
3.open:WebSocket.onopen():连接建立时触发的事件
4.message:WebSocket.onmessage(): 客户端接收服务器端发送的信息时触发
5.error:WebSocket.onerror():通信发生错误时触发
6.close:WebSocket.onclose():连接关闭时触发
7.WebSocket.send():发送信息的方法
8.WebSocket.close():关闭连接方法
SOCKJS
SOCKJS 是一个浏览器使用的js库,它提供了一个类似网络的对象,和连贯的,跨浏览器的jaApi,可以在浏览器和服务器之间创建一个低延迟,全双工的跨域通信通道
SOCKJS实现了对浏览器的兼容,spring框架提供了很多透明的,回退选项,如果遇到低版本的浏览器会自动降级为轮询,支持就用websocket
sockjs-client
sockjs-client 是从SOCKJS分离出来的客户端使用的通信模块
stompjs
STOMP(Simple Text-Orientated Messaging Protocol) 面向消息的简单文本协议;
websocket只是一个消息架构,不强制使用任何的消息协议,为了更好的在浏览器和服务器之间传递消息,使用stomp协议 的stompjs
STOMP与WebSocket 的关系:就是没使用http而使用stomp协议,在浏览器和服务器之间进行消息传递
1.HTTP协议解决了web浏览器发起请求以及web服务器响应请求的细节,假设HTTP协议不存在,只能使用TCP套接字来编写web应用,你可能认为这是一件疯狂的事情;
2.直接使用WebSocket(SockJS)就很类似于使用TCP套接字来编写web应用,因为没有高层协议,就需要我们定义应用间发送消息的语义,还需要确保连接的两端都能遵循这些语义;
3同HTTP在TCP套接字上添加请求-响应模型层一样,STOMP在WebSocket之上提供了一个基于帧的线路格式层,用来定义消息语义、
安装
npm install sockjs-client --save
npm install stompjs --save
引入
import SockJS from 'sockjs-client';
import? Stomp from 'stompjs';
export default {
? ? data(){
? ? ? ? return {
? ? ? ? ? ? stompClient:'',
? ? ? ? ? ? timer:'',
? ? ? ? }
? ? },
? ? methods:{
? ? ? ? initWebSocket() {
? ? ? ? ? ? this.connection();
? ? ? ? ? ? let that= this;
? ? ? ? ? ? // 断开重连机制,尝试发送消息,捕获异常发生时重连
? ? ? ? ? ? this.timer = setInterval(() = {
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? that.stompClient.send("test");
? ? ? ? ? ? ? ? } catch (err) {
? ? ? ? ? ? ? ? ? ? console.log("断线了: " + err);
? ? ? ? ? ? ? ? ? ? that.connection();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }, 5000);
? ? ? ? },?
? ? ? ? connection() {
? ? ? ? ? ? // 建立连接对象
? ? ? ? ? ? let socket = new SockJS('execution-progress/info?t=1593744273983');
????????????var sockjs =new SockJS(url, _reserved, options);
? ? ? ? ? ? ? ? //server(string):添加到url的字符串,默认为随机的4位数
? ? ? ? ? ? ? ? //transports (string OR array of strings):回退传输列表
? ? ? ? ? ? ? ? // sessionId (number OR function):会话标识,函数必须返回一个随机生成的字符串
? ? ? ? ? ? // 获取STOMP子协议的客户端对象
? ? ? ? ? ? this.stompClient = Stomp.over(socket);
? ? ? ? ? ? // 定义客户端的认证信息,按需求配置
? ? ? ? ? ? let headers = {
? ? ? ? ? ? ? ? Authorization:''
? ? ? ? ? ? }
? ? ? ? ? ? // 向服务器发起websocket连接
? ? ? ? ? ? this.stompClient.connect(headers,() = {
? ? ? ? ? ? ? ? this.stompClient.subscribe('/topic/public', (msg) = { // 订阅服务端提供的某个topic
? ? ? ? ? ? ? ? ? ? console.log('广播成功')
? ? ? ? ? ? ? ? ? ? console.log(msg);? // msg.body存放的是服务端发送给我们的信息
? ? ? ? ? ? ? ? },headers);
? ? ? ? ? ? ? ? this.stompClient.send("/app/chat.addUser",
? ? ? ? ? ? ? ? ? ? headers,
? ? ? ? ? ? ? ? ? ? JSON.stringify({sender: '',chatType: 'JOIN'}),
? ? ? ? ? ? ? ? )? //用户加入接口
? ? ? ? ? ? }, (err) = {
? ? ? ? ? ? ? ? // 连接发生错误时的处理函数
? ? ? ? ? ? ? ? console.log('失败')
? ? ? ? ? ? ? ? console.log(err);
? ? ? ? ? ? });
? ? ? ? },? ? //连接 后台
? ? ? ? disconnect() {
? ? ? ? ? ? if (this.stompClient) {
? ? ? ? ? ? ? ? this.stompClient.disconnect();
? ? ? ? ? ? }
? ? ? ? },? // 断开连接
? ? },
? ? mounted(){
? ? ? ? this.initWebSocket();
? ? },
? ? beforeDestroy: function () {
? ? ? ? // 页面离开时断开连接,清除定时器
? ? ? ? this.disconnect();
? ? ? ? clearInterval(this.timer);
? ? }
}
如何使用WebSocket
WebSocket的出现是基于Web应用的实时性需要而产生的。这种实时的Web应用大家应该不陌生,在生活中都应该用到过,比如新浪微博的评论、私信的通知,腾讯的WebQQ等。让我们来回顾下实时 Web 应用的窘境吧。
在WebSocket出现之前,一般通过两种方式来实现Web实时用:轮询机制和流技术;其中轮询有不同的轮询,还有一种叫Comet的长轮询。
轮询:这是最早的一种实现实时 Web 应用的方案。客户端以一定的时间间隔向服务端发出请求,以频繁请求的方式来保持客户端和服务器端的同步。这种同步方案的缺点是,当客户端以固定频率向服务 器发起请求的时候,服务器端的数据可能并没有更新,这样会带来很多无谓的网络传输,所以这是一种非常低效的实时方案。
长轮询:是对定时轮询的改进和提高,目地是为了降低无效的网络传输。当服务器端没有数据更新的时候,连接会保持一段时间周期直到数据或状态改变或者 时间过期,通过这种机制来减少无效的客户端和服务器间的交互。当然,如果服务端的数据变更非常频繁的话,这种机制和定时轮询比较起来没有本质上的性能的提 高。
流:常就是在客户端的页面使用一个隐藏的窗口向服务端发出一个长连接的请求。服务器端接到这个请求后作出回应并不断更新连接状态以保证客户端和服务 器端的连接不过期。通过这种机制可以将服务器端的信息源源不断地推向客户端。这种机制在用户体验上有一点问题,需要针对不同的浏览器设计不同的方案来改进 用户体验,同时这种机制在并发比较大的情况下,对服务器端的资源是一个极大的考验。
上述方式其实并不是真正的实时技术,只是使用了一种技巧来实现的模拟实时。在每次客户端和服务器端交互的时候都是一次 HTTP 的请求和应答的过程,而每一次的 HTTP 请求和应答都带有完整的 HTTP 头信息,这就增加了每次传输的数据量。但这些方式最痛苦的是开发人员,因为不论客户端还是服务器端的实现都很复杂,为了模拟比较真实的实时效果,开发人员 往往需要构造两个HTTP连接来模拟客户端和服务器之间的双向通讯,一个连接用来处理客户端到服务器端的数据传输,一个连接用来处理服务器端到客户端的数 据传输,这不可避免地增加了编程实现的复杂度,也增加了服务器端的负载,制约了应用系统的扩展性。
基于上述弊端,实现Web实时应用的技术出现了,WebSocket通过浏览器提供的API真正实现了具备像C/S架构下的桌面系统的实时通讯能 力。其原理是使用JavaScript调用浏览器的API发出一个WebSocket请求至服务器,经过一次握手,和服务器建立了TCP通讯,因为它本质 上是一个TCP连接,所以数据传输的稳定性强和数据传输量比较小。
WebSocket 协议
WebSocket 协议本质上是一个基于 TCP 的协议。为了建立一个 WebSocket 连接,客户端浏览器首先要向服务器发起一个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了一些附加头信息,其中附加头信息”Upgrade: WebSocket”表明这是一个申请协议升级的 HTTP 请求,服务器端解析这些附加的头信息然后产生应答信息返回给客户端,客户端和服务器端的 WebSocket 连接就建立起来了,双方就可以通过这个连接通道自由的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。
下面我们来详细介绍一下 WebSocket 协议,由于这个协议目前还是处于草案阶段,版本的变化比较快,我们选择目前最新的 draft-ietf-hybi-thewebsocketprotocol-17 版本来描述 WebSocket 协议。因为这个版本目前在一些主流的浏览器上比如 Chrome,、FireFox、Opera 上都得到比较好的支持。通过描述可以看到握手协议
客户端发到服务器的内容:
代码如下 复制代码
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin:
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
从服务器到客户端的内容:
代码如下 复制代码
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
这些请求和通常的 HTTP 请求很相似,但是其中有些内容是和 WebSocket 协议密切相关的。我们需要简单介绍一下这些请求和应答信息,”Upgrade:WebSocket”表示这是一个特殊的 HTTP 请求,请求的目的就是要将客户端和服务器端的通讯协议从 HTTP 协议升级到 WebSocket 协议。其中客户端的Sec-WebSocket-Key和服务器端的Sec-WebSocket-Accept就是重要的握手认证信息了,这些内容将在服 务器端实现的博文中讲解。
相信通过上文的讲解你应该对WebSocket有了个初步认识了,如果有任何疑问欢迎交流。
客户端
如概念篇中介绍的握手协议,客户端是由浏览器提供了API,所以只要使用JavaScript来简单调用即可,而服务器端是要自己实现的,服务器端将在下个博文来讲。
代码如下 复制代码
WebSocket JavaScript 接口定义:
[Constructor(in DOMString url, optional in DOMString protocol)]
interface WebSocket {
readonly attribute DOMString URL;
// ready state
const unsigned short CONNECTING = 0;
const unsigned short OPEN = 1;
const unsigned short CLOSED = 2;
readonly attribute unsigned short readyState;
readonly attribute unsigned long bufferedAmount;
// networking
attribute Function onopen;
attribute Function onmessage;
attribute Function onclose;
boolean send(in DOMString data);
void close();
};
WebSocket implements EventTarget;
简单了解下接口方法和属性:
readyState表示连接有四种状态:
CONNECTING (0):表示还没建立连接;
OPEN (1): 已经建立连接,可以进行通讯;
CLOSING (2):通过关闭握手,正在关闭连接;
CLOSED (3):连接已经关闭或无法打开;
url是代表 WebSocket 服务器的网络地址,协议通常是”ws”或“wss(加密通信)”,send 方法就是发送数据到服务器端;
close 方法就是关闭连接;
onopen连接建立,即握手成功触发的事件;
onmessage收到服务器消息时触发的事件;
onerror异常触发的事件;
onclose关闭连接触发的事件;
JavaScript调用浏览器接口实例如下:
代码如下 复制代码
var wsServer = 'ws://localhost:8888/Demo'; //服务器地址
var websocket = new WebSocket(wsServer); //创建WebSocket对象
websocket.send("hello");//向服务器发送消息
alert(websocket.readyState);//查看websocket当前状态
websocket.onopen = function (evt) {
//已经建立连接
};
websocket.onclose = function (evt) {
//已经关闭连接
};
websocket.onmessage = function (evt) {
//收到服务器消息,使用evt.data提取
};
websocket.onerror = function (evt) {
//产生异常
};