webSocket入门

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/woshishuiaaaD/article/details/52767878

webSocket入门

1.百度百科:WebSocket protocol 是HTML5一种新的协议。它实现了浏览器与服务器全双工通信(full-duplex)。一开始的握手需要借助HTTP请求完成。

2.介绍下现在世面上经常用的桥梁技术:

轮询:这是最早的一种实现实时 Web 应用的方案。客户端以一定的时间间隔向服务端发出请求,以频繁请求

的方式来保持客户端和服务器端的同步。这种同步方案的缺点是,当客户端以固定频率向服务 器发起请求的

时候,服务器端的数据可能并没有更新(服务端会即时返回给客户端响应),这样会带来很多无谓的网络传输,

所以这是一种非常低效的实时方案,一般会选择通过ajax异步定时请求服务端,服务器去判断是否生成对应的

数据,如果有则返回给客户端,客户端再去做响应的逻辑处理。但是这种方法定时会发http请求,不管是对客

户端还是服务端,都会有较大的负担。

长轮询:是对定时轮询的改进和提高,目地是为了降低无效的网络传输。当服务器端没有数据更新的时候,

连接会保持一段时间周期直到数据或状态改变或者 时间过期,通过这种机制来减少无效的客户端和服务器间的

交互。当然,如果服务端的数据变更非常频繁的话,这种机制和定时轮询比较起来没有本质上的性能的提高,

看网上的介绍,长轮询是轮询的修改版,在客户端发送ajax请求,服务端接收请求但不会立即返回响应,而是

保持这个连接,当产生要返回给客户端的消息时,才发送响应给客户端。这种方式服务端的压力会比较大,

我一般使用的是tomcat,众所周知tomcat是有最大连接数的,当你的客户端一直保持着这个连接,服务端不仅

要不断的去做逻辑处理,还需要保持这些连接

   :常就是在客户端的页面使用一个隐藏的窗口向服务端发出一个长连接的请求。服务器端接到这个请求后作出回应并不断更新连接状态以保证客户端和服务 器端的连接不过期。通过这种机制可以将服务器端的信息源源不断地推向客户端。这种机制在用户体验上有一点问题,需要针对不同的浏览器设计不同的方案来改进 用户体验,同时这种机制在并发比较大的情况下,对服务器端的资源是一个极大的考验。(套用大神的介绍,没有亲自使用过

上述方式其实并不是真正的实时技术,只是使用了一种技巧来实现的模拟实时。在每次客户端和服务器端交互的时候都是一次 HTTP

的请求和应答的过程,而每一次的 HTTP 请求和应答都带有完整的 HTTP 头信息,这就增加了每次传输的数据量,这不可避免地增加

了编程实现的复杂度,也增加了服务器端的负载,制约了应用系统的扩展性。

WebSocket 协议:

WebSocket 协议本质上是一个基于 TCP 的协议。为了建立一个 WebSocket 连接,客户端浏览器首先要向

服务器发起一个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了一些附加头信息,其中附加头信

息”Upgrade: WebSocket”表明这是一个申请协议升级的 HTTP 请求,服务器端解析这些附加的头信息然后产生

应答信息返回给客户端,客户端和服务器端的 WebSocket 连接就建立起来了,双方就可以通过这个连接通道自由

的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。

3.一个讲解的比较详细的博文,有些地方我看不懂。https://my.oschina.net/u/1266171/blog/357488


4.webSocket实例(java后端):

spring是支持webSocket的,具体的步骤如下:

1.注册webSocket服务实例

2.构造服务实例

3.前端开启webSocket的脚本代码


1.写一个配置类,注册webSocket服务实例

@Configuration//指明这是一个配置类
@EnableWebSocket//告诉spring开启webSocket功能

public class WebSocketConfig implements WebSocketConfigurer{

//这个配置类需要实现WebSocketConfigurer,重写两个方法

@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myHandler(), "/charging").setAllowedOrigins("*")
;

//注册这个webSocket服务实例,addHandler有两个参数,第一个是指明服务实例,第二个是访问

服务端服务实例的地址。

}

@Bean
public WebSocketHandler myHandler() {
return new
ServerWBHandler();
}

}


2.构造服务实例

public class TestHandler extends TextWebSocketHandler{

//需要继承TextWebSocketHandler类,

@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
log.info("关闭webSocket连接"+session.getId());
super.afterConnectionClosed(session, status);
}

@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
log.info("开启webSocket连接");
super.afterConnectionEstablished(session);
}

public TestHandler() {
log.info("创建testHandler实例");
}

@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
//UI在用js调用websocket.send()时候,会调用该方法,可以做相应的业务逻辑
String param = message.getPayload();//获取请求参数
log.info("请求参数:"+param);
int i = 0 ;
while(true){

String responseData = JSON.toJSONString(new HashMap().put("responseData","data"+i));
TextMessage tm = new TextMessage(responseData);
session.sendMessage(tm);//发送响应数据到客户端
++i;

}
}

//继承TextWebSocketHandler,重写handleTextMessage方法,服务端开启webSocket后处理的业务逻辑

基础都在这个方法中,用循环来控制服务不断发消息给客户端,1.我没实验,等周一去公司再实验,

如果代码直接执行完后,会产生什么样的结果,是直接断开连接,还是一直保持连接,不做任何处理,

2.服务端怎么主动关闭连接。有待测试,

}



3.前端开启webSocket的脚本代码

前端代码用的是html加js,只粘js代码了,只要触发这个函数就可以了:

<script type="text/javascript">
var i = 0 ;
var ws ; 
//开启webSocket
function startWebSocket(){
console.log("准备开启webSocket");
//判断浏览器是否webSocket
if ("WebSocket" in window) {
var url = "ws://192.168.1.52:80/testPath";//请求的地址,使用的ws协议,ws对http协议进行了封装 
ws = new WebSocket(url);

ws.onopen = function(event){
/**
* 1.webSocket进行握手连接,连接成功后触发此函数,可以使用send():发送请求数据,这个数据可以是json类型.
* 2.在调用send(data)时,需要确保已经成功建立连接,否则会报错
* */
var requestData = {'param1':'value1','param2':'value2'};
ws.send(requestData);//发送请求数据
};

ws.onmessage = function(event){
/**
* 1.接受服务端返回的响应信息,服务端返回一个event对象,返回的数据封装在event.data(服务端只要返回数据都会触发这个函数,
* 服务端可以用while来持续给浏览器端发送响应数据,浏览器端可以根据响应数据做一些判断,比如响应信息中存在某个标记后关闭webSocket)
*/
var responseData= event.data;
console.log(responseData+"-num-"+i);
++i;

}
ws.onerror = function(event){
/**
* 1.当通信出现错误时会触发此函数

*/

}

ws.onclose = function(event){
/**
* 1.当连接关闭事触发此函数
*/
console.log("webSocket连接关闭");
}

}else{
console.log("浏览器不支持webSocket");
}



}

function closeWebSocket(){
ws.close();//主动关闭webSocket,但不是即时关闭
}
function endWebSocket(){
console.log("关闭webSocket程序--------------------------------");
closeWebSocket();

}

</script>


在webSocket使用过程中发现了不少问题,一个是服务端的压力到底符合,还有就是webSocket关闭的问题,

在client中调用ws.close不能即时关闭webSocket或者不能关闭webSocket,这个问题比较严重,会加大服务端的压力,当并发访问时内存溢出时很有可能的。


写给自己:

最近还是太懒了,webSocket这篇文章在草稿箱放了很久了,并且在写博客的时候也没有很用心,没有去

更多深入的去研究这门技术,一个是自己懒,惯着自己,时光不再来,望自己谨记。

10.31公司要开启996模式了,敬成长的自己。离过年更近了,自己定的计划还差很多,加油,我现在是一个初级工程师,5年后我会是一位架构师。

业精于勤荒于嬉,@洪水猛兽



展开阅读全文

没有更多推荐了,返回首页