一、简介
定义:
WebSocket是HTML5新增加的一种通信协议,目前流行的浏览器都支持这个协议,例如Chrome,Safari,Firefox,Opera,IE等。
特点:
服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种
建立在 TCP 协议之上,服务器端的实现比较容易
可以发送文本,也可以发送二进制数据
没有同源限制,客户端可以与任意服务器通信
协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。如ws://localhost/Test/websocket
http://www.runoob.com/html/html5-websocket.html
原理:
https://blog.csdn.net/zwto1/article/details/52493119
https://www.cnblogs.com/fuqiang88/p/5956363.html
https://blog.csdn.net/pedrojuliet/article/details/66974844
二、入门案例
少说废话,上代码。。。
java服务端:
package DEMO;
import java.io.IOException;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
//该注解用来指定一个URI,客户端可以通过这个URI来连接到WebSocket。
@ServerEndpoint("/websocket")
public class WebSocket {
//与客户端通信的seesion会话
private Session session;
//监听客户端连接成功
@OnOpen
public void onOpen(Session session){
this.session = session;
System.out.println("Client connected");
}
//监听客户端断开连接
@OnClose
public void onClose(Session session){
this.session = session;
System.out.println("Connection closed");
}
//接收到客户端传过来的数据,处理与客户端之间的业务数据通信
@OnMessage
public void onMessage(String message, Session session) throws IOException, InterruptedException{
System.out.println("Received: " + message);
//发送消息给客户端
session.getBasicRemote().sendText("发送消息给客户端");
int countMessages = 0; //发送消息数
while(countMessages < 6){
Thread.sleep(3000);
session.getBasicRemote().sendText("发送第"+countMessages+"个消息给客户端");
countMessages++;
}
}
//发生错误是调用
@OnError
public void onError(Session session, Throwable error){
System.out.println("发生错误");
error.printStackTrace();
}
}
js客户端:
<script>
//检查浏览器是否支持websocket
if(window.WebSocket) {
console.log('浏览器支持websocket');
}else{
console.log('浏览器不支持websocket');
}
//创建一个WebSocket对象,参数为连接的服务端地址
var webSocket = new WebSocket('ws://localhost/Test/websocket');
//WebSocket连接成功触发事件
webSocket.onopen = function(event) {
console.log("websocket连接成功");
webSocket.send('hello'); //发送数据给服务端
};
//WebSocket发生错误时触发事件
webSocket.onerror = function(event) {
console.log("websocket连接发生错误:" + event.data);
};
//WebSocket断开连接触发事件
webSocket.onclose = function(event) {
console.log("websocket断开连接");
};
//接收服务端传过来的数据
webSocket.onmessage = function(event) {
console.log("客户端接收到服务端返回的数据:" + event.data);
};
//点击事件 发送数据
function start() {
webSocket.send('hello'); //发送数据给服务端
return false;
}
</script>
测试运行:页面打印
三、springboot整合webSocket
参考博客:https://blog.csdn.net/u012977315/article/details/84944708
步骤如下:
1、添加websocket依赖
<!-- websocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2、开启webSocket配置
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
3、编写webSocket服务端
@Component
@ServerEndpoint(value = "/websocket/{platformType}/{userId}")//申明这是websocket服务端点
public class WebSocketServer {
private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
public static int onlineCount = 0;
//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
public static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
//与某个客户端的连接会话,需要通过它来给客户端发送数据
public Session session;
//接收参数中的用户ID
public Long userId;
//接收用户中的平台类型
public Integer platformType;
/**
* 监听客户端打开连接
* 接收url中的参数
*/
@OnOpen
public void onOpen(Session session, @PathParam("platformType") Integer platformType, @PathParam("userId") Long userId) {
this.session = session;
this.userId = userId;
this.platformType = platformType;
webSocketSet.add(this); //加入set中
addOnlineCount(); //在线数加1
log.info("有新连接加入!当前在线人数为" + getOnlineCount() + " userId==== " + userId + " platformType==== " + platformType);
try {
sendMessage("连接成功");
} catch (IOException e) {
log.error("websocket IO异常");
}
}
/**
* 监听客户端断开连接
*/
@OnClose
public void onClose() {
webSocketSet.remove(this); //从set中删除
subOnlineCount(); //在线数减1
log.info("有一连接关闭!当前在线人数为" + getOnlineCount());
}
/**
* 收到客户端消息后调用的方法,处理与客户端之间的业务数据通信
*
* @param message 客户端发送过来的消息
* @throws IOException
*/
@OnMessage
public void onMessage(String message, Session session) throws IOException {
log.info("来自客户端的消息:" + message);
sendMessage("处理与客户端之间的业务数据通信成功");
}
/**
* 监听发生错误
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("发生错误" + error);
error.printStackTrace();
}
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
/**
* 私发
*
* @param message
* @throws IOException
*/
public static void sendInfo(Long userId, String message) throws IOException {
for (WebSocketServer item : webSocketSet) {
try {
if (item.userId.equals(userId)) {
item.sendMessage(message);
}
} catch (IOException e) {
continue;
}
}
}
/**
* 群发自定义消息
*/
public static void sendInfos(String message) throws IOException {
log.info(message);
for (WebSocketServer item : webSocketSet) {
try {
item.sendMessage(message);
} catch (IOException e) {
continue;
}
}
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
WebSocketServer.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSocketServer.onlineCount--;
}
}
3、h5前端步骤同上