WebSocket原理及技术简介(转载)

最近有个管理系统项目用到了 websocket,而后我去看了下,这个东西,感受和socket 很像,三次握手。这个是能够直接链接web 和服务端。java

具体差异和特色,再看看。git

下面是本人再别处copy过来转载过来的,就当是本身学习过了。后面若是有用到也能够及时翻看。github

 

业务场景: 当用户D作一个插入或者更新操做时,这个时候,咱们要让ABC用户及时知道。web

技术实现:创建一个socket的长链接,像在用户登录就创建,而后发生D用户操做便可通知ABC用户。浏览器

技术特色:它是一个长链接,对服务器压力会增大,若是是很是大的并发访问,能够想象一下服务器压力,可是胜在及时性,能够及时通知等操做。缓存

技术思考:我感受它就是一个socket,只是应用上面能够对接web端。而后就是能够对某些进行优化,应用场景上,分空闲时期或应用时期能够对socket及时的关闭或者开启,这样可能会让服务器压力小一些。服务器

 

 

 

 

WebSocket用于在Web浏览器和服务器之间进行任意的双向数据传输的一种技术。WebSocket协议基于TCP协议实现,包含初始的握手过程,以及后续的屡次数据帧双向传输过程。其目的是在WebSocket应用和WebSocket服务器进行频繁双向通讯时,可使服务器避免打开多个HTTP链接进行工做来节约资源,提升了工做效率和资源利用率。websocket

1. 引言
互联网发展的早期,网站上只是一些静态展现页面。用户请求(Request)网站页面,网站回复(Response)页面内容给用户浏览器。由于需求简单,因此也没有很复杂的协议过程。这种形式的Request/Response交互流程以下图所示:网络

 

 

图 11 Request/Responsesession

 

    随着互联网技术的发展,带宽逐步提升,用户数也愈来愈庞大。对互联网的呈现内容提出了要求,随之出现了动态页面技术,对同一个页面,页面的某些部分对不一样的访问用户,呈现的内容不一样。相关的实现技术有CGI、ASP、PHP、JSP等。因为访问量的增长,WEB服务器同时处理的用户数也达到了万(10K)以上级别,这就是C10K问题:"The C10K problem"[1]。为了缓解服务器压力,每次Request/Response后链接(TCP链接)继续保持,以及对同一个TCP链接,屡次复用Request/Response的方法(也称为Pipeline)也提了出来。这就是HTTP/1.1协议中长链接的主要内容。

    伴随移动互联网的发展,大量移动终端和其上的APP应用接入网络,HTML5技术也提了出来,以便支持WEB上的音视频播放、实时游戏、实时聊天等。催生了这样一个需求,当服务器有更新时,须要当即将数据发送给客户端,这就是基于服务器端的推送技术。

    WEBSOCKET以前的解决方法大概这么几种: 1)轮询:客户端设置一个时间间隔,时间到之后,向服务器发送request询问有无新数据,服务器当即返回response,若是有更新则携带更新的数据。2)长链接(long poll): 和轮询类似,可是为阻塞模式的轮询,客户端请求新的数据request, 服务器会阻塞请求,直到有新数据后才返回response给客户端;而后客户端再重复此过程。这两种方式的特色,不断的创建HTTP链接,而后发送请求request,以后服务器等待处理。服务端体现的是一种被动性,同时这种处理方式,很是耗费网络带宽和服务器资源。

    服务器向客户端推送更新时,由于被动性,对低延迟的应用体验很差;由于request/response的交互方式,对网络带宽和服务器带来了额外的负担(例如屡次请求的HTTP头部, TCP链接复用会致使的Head-of-Line Blocking线头阻塞[2]等)。若是在单一的TCP链接中,使用双向通讯(全双工通讯)就能很好的解决此问题。这就是WebSocket技术的原因。

 

2. WebSocket技术及协议
WebSocket技术的优势有:1)经过第一次HTTP Request创建了链接以后,后续的数据交换都不用再从新发送HTTP Request,节省了带宽资源; 2) WebSocket的链接是双向通讯的链接,在同一个TCP链接上,既能够发送,也能够接收; 3)具备多路复用的功能(multiplexing),也即几个不一样的URI能够复用同一个WebSocket链接。这些特色很是相似TCP链接,可是由于它借用了HTTP协议的一些概念,因此被称为了WebSocket。

2.1 WebSocket API
WebSocket API[3], 也称为WebSocket接口(Interface),定义了Web应用和服务器进行双向通讯的公共接口。 以下图所示:

 

 

图 21 WebSocket API

接口的内容能够分为三类:状态变量、网络功能和消息处理等。

构造函数WebSocket(url, protocols):构造WebSocket对象,以及创建和服务器链接; protocols可选字段,表明选择的子协议
状态变量readyState: 表明当前链接的状态,短整型数据,取值为CONNECTING(值为0), OPEN(值为1), CLOSING(值为2), CLOSED(值为3)
方法变量close(code, reason): 关闭此WebSocket链接。
状态变量bufferedAmount: send函数调用后,被缓存而且未发送到网络上的数据长度
方法变量send(data): 将数据data经过此WebSocket发送到对端
回调函数onopen/onmessage/onerror/onclose: 当相应的事件发生时会触发此回调函数
 2.1.1 示例
客户端使用例子(JavaScript):

 

var websocket = new WebSocket("ws://www.host.com/path");
websocket.onopen = function(evt) { onOpen(evt) };
websocket.onclose = function(evt) { onClose(evt) };
websocket.onmessage = function(evt) { onMessage(evt) };
websocket.onerror = function(evt) { onError(evt) }; }
function onMessage(evt) { alert( evt.data); }
function onError(evt) { alert( evt.data); }
websocket.send("client to server");

 2.2 WebSocket协议
WebSocket当作是一种相似TCP/IP的socket技术;此socket在Web应用中实现,并得到了和TCP/IP通讯同样灵活方便的全双向通讯功能。

WebSocket协议由RFC 6455定义。协议分为两个部分: 握手阶段和数据通讯阶段。

WebSocket为应用层协议,其定义在TCP/IP协议栈之上。WebSocket链接服务器的URI以"ws"或者"wss"开头。ws开头的默认TCP端口为80,wss开头的默认端口为443。

 2.2.1 握手阶段
客户端和服务器创建TCP链接以后,客户端发送握手请求,随后服务器发送握手响应即完成握手阶段。以下图所示:

 

 

图 22 Handshake

客户端握手请求相似以下:


服务器的握手响应相似以下:


 

须要关闭链接时,任意一方直接发送类型为关闭帧(Close frame)的控制帧数据给对方便可。

 2.2.2 数据通讯
WebSocket的数据在发送时,被组织为依次序的一串数据帧(data frame),而后进行传送。

传送的帧类型分为两类:数据帧(data frame)和控制帧(Control frame)。数据帧能够携带文本数据或者二进制数据;控制帧包含关闭帧(Close frame)和Ping/Pong帧。

帧的格式以下所示:

 

 

其中最重要的字段为opcode(4bit)和MASK(1bit):

MASK值,从客户端进行发送的帧必须置此位为1,从服务器发送的帧必须置为0。若是任何一方收到的帧不符合此要求,则发送关闭帧(Close frame)关闭链接。
opcode的值: 0x1表明此帧为文本数据帧, 0x2表明此帧为二进制数据帧, 0x8为控制帧中的链接关闭帧(close frame), 0x9为控制帧中的Ping帧, 0xA(十进制的10)为控制帧中的Pong帧。
Ping/Pong帧: Ping帧和Pong帧用于链接的保活(keepalive)或者诊断对端是否在线。这两种帧的发送和接收不对WEB应用公开接口,由实现WebSocket协议的底层应用(例如浏览器)来实现它。
 2.2.3 链接关闭
任何一端发送关闭帧给对方,便可关闭链接。关闭链接时一般都带有关闭链接的状态码(status code)。常见状态码的含义以下:

1000 链接正常关闭
1001 端点离线,例如服务器down,或者浏览器已经离开此页面
1002 端点由于协议错误而中断链接
1003 端点由于受到不能接受的数据类型而中断链接
1004 保留
1005 保留, 用于提示应用未收到链接关闭的状态码
1006 端点异常关闭
1007 端点收到的数据帧类型不一致而致使链接关闭
1008 数据违例而关闭链接
1009 收到的消息数据太大而关闭链接
1010 客户端由于服务器未协商扩展而关闭
1011 服务器由于遭遇异常而关闭链接
1015 TLS握手失败关闭链接
 3. WebSocket示例
这里以JAVA+Eclipse+TOMCAT+JDK8+浏览器,作为例子。

具体代码见github连接:https://github.com/siwind/HelloWebJava

以回声服务器为例,打开Eclipse,新建Web -- Dynamic Web Project项目,项目名称"HelloWebJava"

 3.1 WebSocket服务端
在项目中新建java类,采用注解的方式,实现OnOpen/OnClose/OnMessage回调方法便可。代码以下:

 

import java.io.IOException;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;


@ServerEndpoint("/WSHello")
public class HelloEndPoint {

@OnOpen
public void onOpen(Session session){
System.out.println("Session " + session.getId() + " has opened a connection");
try {
session.getBasicRemote().sendText("Connection Established");
} catch (IOException ex) {
ex.printStackTrace();
}
}


@OnMessage
public void onMessage(String message, Session session){
System.out.println("Message from " + session.getId() + ": " + message);

try {
session.getBasicRemote().sendText(message);
} catch (IOException ex) {
ex.printStackTrace();
}
}


@OnClose
public void onClose(Session session){
System.out.println("Session " +session.getId()+" has closed!");
}

/**
* 注意: OnError() 只能出现一次. 其中的参数都是可选的。
* @param session
* @param t
*/
@OnError
public void onError(Session session, Throwable t) {
t.printStackTrace();
}

}


3.2 WebSocket浏览器客户端
在项目的WebContent目录下面,新建名称为index.htm的文件,内容以下(部分):


webSocket = new WebSocket(wsUri);
webSocket.onopen =function(event){
if(event.data === undefined)
return;

writeResponse(event.data);
};

webSocket.onmessage =function(event){
writeResponse(event.data);
};

webSocket.onerror =function(event){
writeResponse("<span style='color: red;'>ERROR: </span>Connection error! " + event.data);
};
webSocket.onclose =function(event){
writeResponse("<span style='color: blue;'>INFO: </span>Connection closed. code=" + event.code);
};
}


3.3 部署及运行
在JDK8环境下,部署到Tomcat8.0.x/Tomcat8.5.x/Wildfly10.x/Glassfish4.x,正常运行。以下图所示:

 

 

 

图 31 WebSocket Echo Example

4.  结论
WebSocket和传统的HTTP交互方式的区别以下图:

 

图 41交互方式比较

 

 

WebSocket的结论以下:

基于TCP/IP协议实现
是一种全双向的通讯, 具备底层socket的特色
节约带宽,节省服务器资源
是HTML5的技术之一,具备巨大的应用前景
 

本文的完整示例代码: https://github.com/siwind/HelloWebJava--------------------- 转载:原文:https://blog.csdn.net/yinqingwang/article/details/52565133

相关文章
相关标签/搜索