WebSocket的介绍
2021-04-14 10:28
标签:iso javascrip 通道 接收 get and 两种 界定 一对一 现在,很多网站为了实现推送技术,所用的技术都是 Ajax 轮询或者long poll 。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。 ajax轮询 的原理非常简单,让浏览器隔个几秒就发送一次请求,询问服务器是否有新信息。 long poll 其实原理跟 ajax轮询 差不多,都是采用轮询的方式,不过采取的是阻塞模型(一直打电话,没收到就不挂电话),也就是说,客户端发起连接后,如果没消息,就一直不返回Response给客户端。直到有消息才返回,返回完之后,客户端再次建立连接,周而复始。 从上面可以看出其实这两种方式,都是在不断地建立HTTP连接,然后等待服务端处理,可以体现HTTP协议的另外一个特点,被动性。何为被动性呢,其实就是,服务端不能主动联系客户端,只能有客户端发起。 从上面很容易看出来,不管怎么样,上面这两种都是非常消耗资源的。 WebSocket是HTML5出的东西(协议),也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持持久连接的(长连接,循环连接的不算) 首先HTTP有1.1和1.0之说,也就是所谓的keep-alive,把多个HTTP请求合并为一个,但是Websocket其实是一个新协议,跟HTTP协议基本没有关系,只是为了兼容现有浏览器的握手规范而已,也就是说它是HTTP协议上的一种补充,可以通过这样一张图理解 首先,相对于HTTP这种非持久的协议来说,Websocket是一个持久化的协议。 所以在这种情况下出现了,Websocket出现了。他解决了HTTP的难题。 WebSocket并不是全新的协议,而是利用了HTTP协议来建立连接。我们来看看WebSocket连接是如何创建的。 首先,WebSocket连接必须由浏览器发起,因为请求协议是一个标准的HTTP请求,格式如下: 该请求和普通的HTTP请求有几点不同: 服务器如果接受该请求,就会返回如下响应: 该响应代码 这里开始就是HTTP最后负责的区域了,告诉客户端,已经成功切换协议啦~ websockt心跳机制,不得不说很形象;那何为心跳机制,就是表明client与server的连接是否还在的检测机制; 如果不存在检测,那么网络突然断开,造成的后果就是client、server可能还在傻乎乎的发送无用的消息,浪费了资源;怎样检测呢?原理就是定时向server发送消息,如果接收到server的响应就表明连接依旧存在; (1)Client:客户端说明 ? 客户端的代码主要是使用H5的WebSocket进行实现,在前端网页中使用WebSocket进行连接服务端,然后建立Socket连接进行通讯。 (2)Server:服务端说明 ? 服务端主要是建立多个客户端的关系,进行消息的中转等。客户端成功连接到服务端之后,就可以通过建立的通道进行发送消息到服务端,服务端接收到消息之后在群发给所有的客户端。 (3)客户端和服务端连接 (4)客户端和服务端怎么发送消息? 客户端可以使用webSocket提供的send()方法,如下代码: 服务端怎么发送消息呢?主要是使用在成功建立连接的时候,创建的Session对象进行发送,如下代码: (5)客户端和服务端怎么接受消息? 客户端接收消息消息使用的是websocket的onmessage回调方法,如下代码: 服务端: (6)群聊原理(群发消息) 服务端在和客户端建立连接的时候,会创建一个webSocket对象,我们会将每个连接创建的对象进行报错到一个列表中,比如:CopyOnWriteArraySet(这是线程安全的);在要进行群发的时候,编写我们的列表对象进行群发消息。 (7)单聊原理(一对一消息) 聊的时候,就无需遍历列表,而是需要知道发送者和接受者各自的Session对象,这个Session对象怎么获取呢?Session可以获取到sessionId,发送者在发送消息的时候,携带接收消息的sessionId,那么问题就演变成了:发送者怎么知道接受者的sessionId,那就是加入一个在线用户列表即可,在线用户列表中有用户的基本信息,包括sessionId。 对比聊天室的demo,不同之处在于,客户端连入服务器时候,会开启一个线程,在线程中对客户端进行推送数据。 关键代码: 目前业务还不是很复杂,后期功能添加时候,再进行扩展,关于这个实时推送,大概开了50个窗口就连接失败了。关于websocket的高并发,可以考虑。 WebSocket的介绍 标签:iso javascrip 通道 接收 get and 两种 界定 一对一 原文地址:https://www.cnblogs.com/jimlau/p/12375447.htmlWebSocket
websocket的背景
websocket的特点
Ajax轮询
场景再现:
客户端:啦啦啦,有没有新信息(Request)
服务端:没有(Response)
客户端:啦啦啦,有没有新消息(Request)
服务端:好啦好啦,有啦给你。(Response)
客户端:啦啦啦,有没有新消息(Request)
服务端:。。。。。没。。。。没。。。没有(Response) ---- looplong poll
场景再现:
客户端:啦啦啦,有没有新信息,没有的话就等有了才返回给我吧(Request)
服务端:额。。 等待到有消息的时候。。来 给你(Response)
客户端:啦啦啦,有没有新信息,没有的话就等有了才返回给我吧(Request) -loop
ajax轮询 需要服务器有很快的处理速度和资源。(速度)
long poll 需要有很高的并发,也就是说同时接待客户的能力。(场地大小)
所以ajax轮询 和long poll 缺点非常明显。websocket 与Http的关系
websocket协议建立
GET ws://localhost:3000/ws/chat HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Origin: http://localhost:3000
Sec-WebSocket-Key: client-random-string
Sec-WebSocket-Version: 13
/path/
,而是以ws://
开头的地址;Upgrade: websocket
和Connection: Upgrade
表示这个连接将要被转换为WebSocket连接;Sec-WebSocket-Key
是用于标识这个连接,并非用于加密数据;Sec-WebSocket-Version
指定了WebSocket的协议版本。HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: server-random-string
101
表示本次连接的HTTP协议即将被更改,更改后的协议就是Upgrade: websocket
指定的WebSocket协议。websocket的客户端简单实例
var ws = new WebSocket("wss://localhost:8080/ws/asset");
//连接建立成功调用的方法
ws.onopen = function(evt) {
console.log("Connection open ...");
//向服务端发送消息
ws.send("Hello WebSockets!");
};
//收到服务端消息后调用的方法
ws.onmessage = function(evt) {
console.log( "Received Message: " + evt.data);
ws.close();
};
//连接关闭调用的方法
ws.onclose = function(evt) {
console.log("Connection closed.");
};
webSocket的服务端简单实例
@ServerEndpoint(value = "/ws/asset")
@Component
@Slf4j
public class WebSocketServer {
private static AtomicInteger OnlineCount = new AtomicInteger(0);
// concurrent包的线程安全Set,用来存放每个客户端对应的Session对象。
private static CopyOnWriteArraySet
websocket的心跳机制
这个心跳机制在分布式中也很常见,demo
聊天室demo
var websocket = new WebSocket("ws://localhost:8080/myWs");
var message = document.getElementById('text').value;
websocket.send(message);
session.getAsyncRemote().sendText("恭喜您成功连接上WebSocket");
websocket.onmessage = function(event) {
//文本信息直接显示,如果是json信息,需要转换下在显示.
var data = event.data;
document.getElementById('message').innerHTML += data;
}
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("来自客户端的消息:" + message);
}
websocket的实时推送
/**
* 接收到消息
*
* @param text
*/
@OnMessage
public void onMsg(Session session,@PathParam("param") String param) throws IOException {
//记录客户端
webSocketMaps.put(session, param);
//实例化工作任务
Operater operater =new Operater(session,param);
//开启线程
Thread thread = new Thread(operater);
thread.start();
logger.info("发送线程启动成功");
}
下一篇:css 基础教程学习