初次接触 WebSocket 的人,都会问同样的问题:我们已经有了 HTTP 协议,为什么还需要另一个协议?它能带来什么好处?

答案很简单,因为 HTTP 协议有一个缺陷:通信只能由客户端发起。

举例来说,我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息。

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

它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。

                     

一.传统的实现即时通信的方式

ajax轮询

ajax轮询的原理非常简单,让浏览器隔个几秒就发送一次请求,询问服务器是否有新信息。

场景再现:

客户端:啦啦啦,有没有新信息(Request)

服务端:没有(Response)

客户端:啦啦啦,有没有新信息(Request)

服务端:没有。。(Response)

客户端:啦啦啦,有没有新信息(Request)

服务端:你好烦啊,没有啊。。(Response)

客户端:啦啦啦,有没有新消息(Request)

服务端:好啦好啦,有啦给你。(Response)

客户端:啦啦啦,有没有新消息(Request)

服务端:。。。。。没。。。。没。。。没有(Response) —- loop

long poll

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

场景再现:

客户端:啦啦啦,有没有新信息,没有的话就等有了才返回给我吧(Request)

服务端:额。。 等待到有消息的时候。。来 给你(Response)

客户端:啦啦啦,有没有新信息,没有的话就等有了才返回给我吧(Request) -loop

从上面可以看出其实这两种方式,都是在不断地建立HTTP连接,然后等待服务端处理,可以体现HTTP协议的另外一个特点,被动性。

何为被动性呢,其实就是,服务端不能主动联系客户端,只能有客户端发起。

小姐:

ajax轮询 需要服务器有很快的处理速度和资源。(速度)
long poll 需要有很高的并发,也就是说同时接待客户的能力。(场地大小)

长连接

在页面里嵌入一个隐蔵iframe,将这个隐蔵iframe的src属性设为对一个长连接的请求或是采用xhr请求,服务器端就能源源不断地往客户端输入数据。
优点:消息即时到达,不发无用请求;管理起来也相对方便。
缺点:服务器维护一个长连接会增加开销,当客户端越来越多的时候,server压力大!
实例:Gmail聊天

(1).基于http协议的长连接

在HTTP1.0和HTTP1.1协议中都有对长连接的支持。其中HTTP1.0需要在request中增加”Connection: keep-alive“ header才能够支持,而HTTP1.1默认支持.

http1.0请求与服务端的交互过程:

a)客户端发出带有包含一个header:”Connection: keep-alive“的请求

b)服务端接收到这个请求后,根据http1.0和”Connection: keep-alive“判断出这是一个长连接,就会在response的header中也增加”Connection: keep-alive“,同是不会关闭已建立的tcp连接.

c)客户端收到服务端的response后,发现其中包含”Connection: keep-alive“,就认为是一个长连接,不关闭这个连接。并用该连接再发送request.转到a)

(2).http1.1请求与服务端的交互过程:

a)客户端发出http1.1的请求

b)服务端收到http1.1后就认为这是一个长连接,会在返回的response设置Connection: keep-alive,同是不会关闭已建立的连接.

c)客户端收到服务端的response后,发现其中包含”Connection: keep-alive“,就认为是一个长连接,不关闭这个连接。并用该连接再发送request.转到a)

基于http协议的长连接减少了请求,减少了建立连接的时间,但是每次交互都是由客户端发起的,客户端发送消息,服务端才能返回客户端消息.因为客户端也不知道服务端什么时候会把结果准备好,所以客户端的很多请求是多余的,仅是维持一个心跳,浪费了带宽.

Flash Socket

在页面中内嵌入一个使用了Socket类的 Flash 程序JavaScript通过调用此Flash程序提供的Socket接口与服务器端的Socket接口进行通信,JavaScript在收到服务器端传送的信息后控制页面的显示。
优点:实现真正的即时通信,而不是伪即时。
缺点:客户端必须安装Flash插件,移动端支持不好,IOS系统中没有flash的存在;非HTTP协议,无法自动穿越防火墙。
实例:网络互动游戏。

二.websocket的方式实现服务端消息推送

 

1.什么是socket?什么是websocket?两者有什么区别?websocket是仅仅将socket的概念移植到浏览器中的实现吗?

 

  我们知道,在网络中的两个应用程序(进程)需要全双工相互通信(全双工即双方可同时向对方发送消息),需要用到的就是socket,它能够提供端对端通信,对于程序员来讲,他只需要在某个应用程序的一端(暂且称之为客户端)创建一个socket实例并且提供它所要连接一端(暂且称之为服务端)的IP地址和端口,而另外一端(服务端)创建另一个socket并绑定本地端口进行监听,然后客户端进行连接服务端,服务端接受连接之后双方建立了一个端对端的TCP连接,在该连接上就可以双向通讯了,而且一旦建立这个连接之后,通信双方就没有客户端服务端之分了,提供的就是端对端通信了。我们可以采取这种方式构建一个桌面版的im程序,让不同主机上的用户发送消息。从本质上来说,socket并不是一个新的协议,它只是为了便于程序员进行网络编程而对tcp/ip协议族通信机制的一种封装。

 

socket传送门:http://blog.csdn.net/luokehua789789/article/details/54378264

websocket是html5规范中的一个部分,它借鉴了socket这种思想,为web应用程序客户端和服务端之间(注意是客户端服务端)提供了一种全双工通信机制。同时,它又是一种新的应用层协议,websocket协议是为了提供web应用程序和服务端全双工通信而专门制定的一种应用层协议,通常它表示为:ws://echo.websocket.org/?encoding=text HTTP/1.1,可以看到除了前面的协议名和http不同之外,它的表示地址就是传统的url地址。

Websocket其实是一个新协议,跟HTTP协议基本没有关系,只是为了兼容现有浏览器的握手规范而已,也就是说它是HTTP协议上的一种补充可以通过这样一张图理解

 

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

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

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

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

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

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

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

 

2.websocket的通信原理和机制

既然是基于浏览器端的web技术,那么它的通信肯定少不了http,websocket本身虽然也是一种新的应用层协议,但是它也不能够脱离http而单独存在。具体来讲,我们在客户端构建一个websocket实例,并且为它绑定一个需要连接到的服务器地址,当客户端连接服务端的时候,会向服务端发送一个类似下面的http报文

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

Upgrade: websocket
Connection: Upgrade

这个就是Websocket的核心了,告诉Apache、Nginx等服务器:发起的是websocket协议。

Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13

首先,Sec-WebSocket-Key  是一个Base64 encode的值,这个是浏览器随机生成的,告诉服务器:泥煤,不要忽悠窝,我要验证尼是不是真的是Websocket助理。
然后,Sec_WebSocket-Protocol  是一个用户定义的字符串,用来区分同URL下,不同的服务所需要的协议。简单理解:今晚我要服务A,别搞错啦~
最后,Sec-WebSocket-Version 是告诉服务器所使用的Websocket Draft(协议版本),在最初的时候,Websocket协议还在 Draft 阶段,各种奇奇怪怪的协议都有,而且还有很多期奇奇怪怪不同的东西,什么Firefox和Chrome用的不是一个版本之类的,当初Websocket协议太多可是一个大难题。。不过现在还好,已经定下来啦~大家都使用的一个东西~ 脱水:服务员,我要的是13岁的噢→_→

然后服务器会返回下列东西,表示已经接受到请求, 成功建立Websocket啦!

 

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

 

依然是固定的,告诉客户端即将升级的是Websocket协议,而不是mozillasocket,lurnarsocket或者shitsocket。
然后,Sec-WebSocket-Accept 这个则是经过服务器确认,并且加密过后的 Sec-WebSocket-Key。服务器:好啦好啦,知道啦,给你看我的ID CARD来证明行了吧。。
后面的,Sec-WebSocket-Protocol 则是表示最终使用的协议。

返回的状态码为101,表示同意客户端协议转换请求,并将它转换为websocket协议。以上过程都是利用http通信完成的,称之为websocket协议握手(websocket Protocol handshake),进过这握手之后,客户端和服务端就建立了websocket连接,以后的通信走的都是websocket协议了。所以总结为websocket握手需要借助于http协议,建立连接后通信过程使用websocket协议。同时需要了解的是,该websocket连接还是基于我们刚才发起http连接的那个TCP连接。一旦建立连接之后,我们就可以进行数据传输了,websocket提供两种数据传输:文本数据和二进制数据。

 

至此,HTTP已经完成它所有工作了,接下来就是完全按照Websocket协议进行了。

基于以上分析,我们可以看到,websocket能够提供低延迟,高性能的客户端与服务端的双向数据通信。它颠覆了之前web开发的请求处理响应模式,并且提供了一种真正意义上的客户端请求,服务器推送数据的模式,特别适合实时数据交互应用开发。

对比前面的http的客户端服务器的交互图可以发现WebSocket方式减少了很多TCP打开和关闭连接的操作,WebSocket的资源利用率高。

3.websocket的创建和常用的属性方法

以下 API 用于创建 WebSocket 对象。

var Socket = new WebSocket(url, [protocol] );

以上代码中的第一个参数 url, 指定连接的 URL。第二个参数 protocol 是可选的,指定了可接受的子协议。

WebSocket 属性

以下是 WebSocket 对象的属性。假定我们使用了以上代码创建了 Socket 对象:

属性 描述
Socket.readyState

只读属性 readyState 表示连接状态,可以是以下值:

  • 0 - 表示连接尚未建立。

  • 1 - 表示连接已建立,可以进行通信。

  • 2 - 表示连接正在进行关闭。

  • 3 - 表示连接已经关闭或者连接不能打开。

Socket.bufferedAmount

只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。

CONNECTING:值为0,表示正在连接。

OPEN:值为1,表示连接成功,可以通信了。

CLOSING:值为2,表示连接正在关闭。

CLOSED:值为3,表示连接已经关闭,或者打开连接失败。

 var webSocket = new WebSocket(url);
if(webSocket.readyState == webSocket.CONNECTING){
console.log('连接正在打开');
} webSocket.onopen = function () {
webSocket.send(consumerId);
//可以看到 "连接正在打开"并没有被打印,说明open对应的就是OPEN状态;
if(webSocket.readyState == webSocket.CONNECTING){
console.log('连接正在打开1');
}
if(webSocket.readyState == webSocket.OPEN){
console.log('连接已打开');
}
sendMsg();
window.weui.alert('已经建立连接');
}; //连接关闭时触发
webSocket.onclose = function () {
if(webSocket.readyState == webSocket.CLOSED){
console.log('连接已关闭')
}
window.weui.alert('连接已断开');
}; //连接
webSocket.onerror = function () {
window.weui.alert('连接错误,请稍后再试');
};

可以看到,当onopen触发时,对应的额就是readyState的OPEN状态,不包含OPENING;onclose触发时,对应的就是CLOSED状态,不包含CLOSING状态。

WebSocket 事件

以下是 WebSocket 对象的相关事件。假定我们使用了以上代码创建了 Socket 对象:

事件 事件处理程序 描述
open Socket.onopen 连接建立时触发
message Socket.onmessage 客户端接收服务端数据时触发
error Socket.onerror 通信发生错误时触发
close Socket.onclose 连接关闭时触发

WebSocket 方法

以下是 WebSocket 对象的相关方法。假定我们使用了以上代码创建了 Socket 对象:

方法 描述
Socket.send()

使用连接发送数据

Socket.close()

关闭连接

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title> <script type="text/javascript">
function WebSocketTest()
{
if ("WebSocket" in window)
{
alert("您的浏览器支持 WebSocket!"); // 打开一个 web socket
var ws = new WebSocket("ws://localhost:9998/echo"); ws.onopen = function()
{
// Web Socket 已连接上,使用 send() 方法发送数据
ws.send("发送数据");
alert("数据发送中...");
}; ws.onmessage = function (evt)
{
var received_msg = evt.data;
alert("数据已接收...");
}; ws.onclose = function()
{
// 关闭 websocket
alert("连接已关闭...");
};
} else
{
// 浏览器不支持 WebSocket
alert("您的浏览器不支持 WebSocket!");
}
}
</script> </head>
<body> <div id="sse">
<a href="javascript:WebSocketTest()">运行 WebSocket</a>
</div> </body>
</html>

用websocket发送接受二进制数据

WebSocket可以通过ArrayBuffer,发送或接收二进制数据。

var socket = new WebSocket('ws://127.0.0.1:8081');
socket.binaryType = 'arraybuffer'; // Wait until socket is open
socket.addEventListener('open', function (event) {
// Send binary data
var typedArray = new Uint8Array(4);
socket.send(typedArray.buffer);
}); // Receive binary data
socket.addEventListener('message', function (event) {
var arrayBuffer = event.data;
// ···
});

目前websocket的缺点是不兼容低版本浏览器。

WebSocket 有没有可能取代 AJAX ?

Websocket(一)——原理及基本属性和方法的更多相关文章

  1. WebSocket的原理,以及和Http的关系

    一.WebSocket是HTML5中的协议,支持持久连接:而Http协议不支持持久连接. 首先HTMl5指的是一系列新的API,或者说新规范,新技术.WebSocket是HTML5中新协议.新API. ...

  2. 深入解析ThreadLocal 详解、实现原理、使用场景方法以及内存泄漏防范 多线程中篇(十七)

    简介 从名称看,ThreadLocal 也就是thread和local的组合,也就是一个thread有一个local的变量副本 ThreadLocal提供了线程的本地副本,也就是说每个线程将会拥有一个 ...

  3. String类原理分析及部分方法

    //String类原理分析及部分方法 //http://www.cnblogs.com/vamei/archive/2013/04/08/3000914.html //http://www.cnblo ...

  4. WebSocket的原理,以及和Http的关系 (转载)

    一.WebSocket是HTML5中的协议,支持持久连接:而Http协议不支持持久连接. 首先HTMl5指的是一系列新的API,或者说新规范,新技术.WebSocket是HTML5中新协议.新API. ...

  5. WebSocket协议-原理篇

    本篇文章主要讲述以下几点: WebSocket的原理与机制 WebSocket与Socket.io WebSocket兼容性 WebSocket的原理与机制 WebSocket协议分为两部分:握手和数 ...

  6. nginx支持websocket及websocket部分原理介绍

    nginx支持websocket及websocket部分原理介绍最近ipc通过websocket与server进行通行,经过无法通过nginx进行反向代理,只有直连nodejs端口.而且部署到阿里云用 ...

  7. .NET应用程序调试—原理、工具、方法

    阅读目录: 1.背景介绍 2.基本原理(Windows调试工具箱..NET调试扩展SOS.DLL.SOSEX.DLL) 2.1.Windows调试工具箱 2.2..NET调试扩展包,SOS.DLL.S ...

  8. javascript数组(1) ——sort的工作原理及其他数组排序方法

    一说到数组排序,最直观的想法就是用sort啊! 请问不用使用sort方法还可以使用什么方法进行数组排序? 比如 :  快速排序法.合并排序法.冒泡排序法.选择排序法.插入排序法.布尔排序法.交互排序. ...

  9. Javascript数组(1)--基本属性及方法

    数组Array是Javascript语言中非常重要的两种引用类型数据之一,另外一种为对象Object.Array的数据模型可分为两种进行存储:堆栈结构.队列结构. 昨天,确切说是前天了,去和大学同学见 ...

随机推荐

  1. 转:日志插件 log4net 的使用

    文本格式说明 可以记载的日志类别包括:FATAL(致命错误).ERROR(一般错误).WARN(警告).INFO(一般信息).DEBUG(调试信息). 文本参数说明 %m(message):输出的日志 ...

  2. apache配置CA证书通过https通信

    Apache Httpd 2.2 实现https加密通讯 实际生产中CA证书一般是向一些专业认证的国际机构来进行申请的.我们会模拟使用OpenSSL生成的证书,来实现Apache的安全加密通讯,这与实 ...

  3. c#中//注释和///注释的区别

    c#中//注释和///注释的区别 ///会被编译,//不会所以使用///会减慢编译的速度(但不会影响执行速度)///会在其它的人调用你的代码时提供智能感知 也是一种注释,但是这种注释主要有两种作用:1 ...

  4. January 29th, 2018 Week 05th Monday

    Losing all hope was freedom. 彻底绝望就是真正的自由. Losing all the hopes, and we are free to challenge everyth ...

  5. The resource configuration is not modifiable in this context.

    项目中使用了Jersey RESTful 框架, 更新代码后服务能正常起来, 在页面登录时验证码不显示 后台报错 java.lang.IllegalStateException: The resour ...

  6. Apha冲刺! Day2 - 砍柴

    Alpha冲刺! Day2 - 砍柴 今日已完成 晨瑶:没做和主项目相关的事情,除了教队友用gitkraken. 昭锡:学习LitePal对数据库进行操作. 永盛:切换 API 管理平台,继续撰写 A ...

  7. ApplicationContext中Bean的生命周期

    引言 Bean应用上下文中的生命周期和在BeanFactory中生命周期类似,不同的是,如果Bean实现了org.springframework.context.ApplicationContextA ...

  8. redis面试必问

    1.项目中缓存是如何使用的?为什么要用缓存?缓存使用不当会造成什么后果? 面试题剖析 为什么要用缓存? 用缓存,主要有两个用途:高性能.高并发. 高性能 假设这么个场景,你有个操作,一个请求过来,吭哧 ...

  9. Java中equals()和“==”区别

    1.对于基础数据类型,使用“=="比较值是否相等: 2.对于复合数据类型(类),使用equals()和“==”效果是一样的,两者比较的都是对象在内存中的存放地址(确切的说,是堆内存地址). ...

  10. centos7下安装docker(8.2进入容器)

    那些在后台运行的新建的容器,通常不是我们想要的,我们要进行一些修改,比如安装服务,创建用户,查看日志,调整网络等等,这些操做都要进入容器去进行修改,今天我们来讨论如何进入容器. 1.docker at ...