网站底部的在线人数是如何统计的?-WebSocket探究
我的博客地址http://www.autunomy.top/blog
可能大家如果细心点会发现,网站底部有一个统计当前在线人数的功能,但是一般来说,网站会利用当前登陆用户数量来统计当前在线人数,coding网站并没有强制用户登陆,但是为什么也能实时统计在线人数?
WebSocket协议
http协议是一个单工,只能是客户端发起请求,服务端处理后返回给客户端,不能由服务端主动发送消息,所以不能使用http请求来统计在线人数
WebSocket协议是基于TCP的一种新的网络协议。它实现了客户端与服务器全双工通信,学过计算机网络都知道,既然是全双工,就说明了服务器可以主动发送信息给客户端。
全双工
:全双工(Full Duplex)是通讯传输的一个术语。. 通信允许数据在两个方向上同时传输,它在能力上相当于两个单工通信方式的结合。. 全双工指可以同时(瞬时)进行信号的双向传输(A→B且B→A)。 指A→B的同时B→A,是瞬时同步的。. 单工 就是在只允许甲方向乙方传送信息,而乙方不能向甲方传送 。
coding网站实现的方法是:coding使用的技术是vue,有一个根组件就是app,所以我们在app组件中,创建websocket连接。但是会有一个bug:当用户使用同一个浏览器打开多个coding的页面,就会创建多个连接,如何解决呢?
解决方法:在创建连接的时候,将客户端ip或者随机uuid发送给服务器,作为唯一标识。如果使用到后者,那么就需要在浏览器本地缓存中进行存储,当浏览器又打开一个coding页面的时候,就将之前存储的uuid发送给服务端,这样就能保证同一个浏览器无论打开多少网页只会统计一个连接。
SpringBoot集合WebSocket
首先需要添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
开启对WebSocket的支持
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
在这里大家可能会遇到一个问题,就是在使用junit单元测试的时候,会爆这个类的错误,但是目前还没有什么好办法,只能是在使用测试类的同时注释掉这段代码,在结束测试之后打开即可,如果大家有好的解决方法可以通过之后的评论中给博主进行解答
编写Service
@Component
@Slf4j
@Service
@ServerEndpoint("/websocket")//这里写的是websocket的url
public class WebSocketService {
//注意这里的stringRedisTemplate以及setStringRedisTemplate方法是为了注入redis的操作对象,如果项目中不使用redis就可以删掉这段代码,如果使用redis,必须使用这种方式进行注入,因为静态的变量不能使用@Autowired直接注入
public static StringRedisTemplate stringRedisTemplate;
@Resource
public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate) {
WebSocketService.stringRedisTemplate = stringRedisTemplate;
}
//建立连接之后的执行的方法
@OnOpen
public void onOpen(Session session) {
log.info("有新的客户端上线");
}
//连接关闭之后执行的方法
@OnClose
public void onClose() {
log.info("有客户端离线");
}
//连接出错的结果
@OnError
public void onError(Throwable throwable) {
throwable.printStackTrace();
}
//客户端给服务器发送消息执行的方法
@OnMessage
public void onMessage(String message) {
log.info("收到客户端发来的消息: {}", message);
}
//给客户端发送消息的方法 这里的WebSocketMessage是自定的类
private void sendTo(WebSocketMessage message) {
}
}
WebSocketMessage类
//websocket消息类 这里的注解是lombok注解
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WebSocketMessage {
private String userId;
private String message;
}
Vue使用WebSocket
let socket = null;
onMounted(() => {
socket = new WebSocket(socketUrl);
//建立连接
socket.onopen = () => {
socket.send("建立连接")
}
//发送消息
socket.send("你好")
//接收消息
socket.onmessage = () => {
}
//断开连接执行的方法
socket.onclose = () => {
console.log("断开连接!");
}
})
onUnmounted(() => {
socket.close();
})
WebSocket的应用其实很广泛,其实qq之类的聊天软件也使用到了WebSocket协议,并不是很难,大家其实自己动手敲一遍代码基本就会使用了