一次握手,双向数据传输
介绍:特点是一次握手,双向数据传输
出现原因:http协议的生命周期是 客户端发送请求,服务端接收响应,缺点是服务端无法在客户端未发送请求的情况下主动发送信息,websocket就是在这种情况下产生的,在建立连接后实现双通道传输。
springboot整合websocket
依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> <version>2.1.3.RELEASE</version> </dependency>
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.75</version> </dependency>
|
配置类
1 2 3 4 5 6 7 8 9 10 11 12
| @Configuration public class WebSocketConfig {
@Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }
|
实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
| @ServerEndpoint(value = "/connect") @Component public class WebSocketServer {
private static Logger log = LoggerFactory.getLogger(WebSocketServer.class);
private static int onlineCount = 0;
private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();
private Session session;
private String sid = "";
@OnOpen public void onOpen(Session session, @PathParam("sid") String sid) { this.session = session; webSocketSet.add(this); addOnlineCount(); if(!"".equals(sid)){ log.info("有新的连接加入:sid="+sid+""); } log.info( "当前在线人数为" + getOnlineCount()); this.sid = sid;
try { sendMessage("连接成功"); } catch (IOException e) { log.error("websocket IO异常"); } }
@OnClose public void onClose() { webSocketSet.remove(this); subOnlineCount(); log.info("有一连接关闭!当前在线数为" + getOnlineCount()); }
@OnMessage public void onMessage(String message, Session session) { BaseResult result = new BaseResult(); JSONObject param = JSONObject.parseObject(message); System.out.println(param.get("test")); try{ System.out.println("这里执行操作"); result.setStatus("OK"); result.setCode("200"); result.setMsg("执行成功"); session.getAsyncRemote().sendText(JSON.toJSONString(result)); } catch (Exception e) { e.printStackTrace(); result.setStatus("fail"); result.setCode("406"); result.setMsg(e.getMessage()); session.getAsyncRemote().sendText(JSON.toJSONString(result)); } }
@OnError public void onError(Session session, Throwable error) { log.error("发生错误"); error.printStackTrace(); }
public void sendMessage(String message) throws IOException { this.session.getBasicRemote().sendText(message); }
public static void sendInfo(String message, @PathParam("sid") String sid) throws IOException { log.info("推送消息到窗口" + sid + ",推送消息内容:" + message); for (WebSocketServer item : webSocketSet) { try { if (sid == null) { item.sendMessage(message); } else if (item.sid.equals(sid)) { 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--; }
}
|
注:
实现类中
@OnOpen注解的方法为第一次握手执行
@OnMessage注解的方法为连接后数据传输执行的
测试方法:
网络找websocket在线测试工具,介绍网站 工具网站
地址为 ws://IP:端口/connect 注:connect为@ServerEndpoint注解设置的
先连接,后发送信息如
扩展:
网上搜索websocket的时候,都提到了ajax和long poll,记录自己理解
ajax:一直发送请求,一直轮询,有新消息就接收,所以ajax一般用在保证实时性高的地方,如项目开发中的可视化数据展示
long poll:长轮询,后端接收到前端的消息后,后端在进行处理的时候如果处理时间很长就会将该请求一直等待,直到处理完毕后,才将响应返回