Websocket 基本原理
Websocket 与 HTTP 比较
- HTTP 连接模式:
- 客户端主动发起请求,服务器端响应请求,响应报文发出,此连接生命周期即结束,再次客户端请求,再次开启连接…
- 这里客户端作为主动请求者,服务端作为消息的被动响应者
- 服务器端无法在客户端未发起请求时向其发送消息
------------------------------------------
| HTTP |
------------------------------------------
---------- ----------
| Client | | Server |
---------- ----------
| Request |
| ---------------------> | ||
| Response | ||
| <--------------------- | ||
| Request |
| ---------------------> | ||
| Response | ||
| <--------------------- | ||
| ... |
* || Connect lifecycle
- Websocket 连接模式:
- 也是由客户端发起握手请求,服务器端发送确认信息,此时,连接升级为Websocket请求
- 升级为Websocket请求之后,连接变为全双工通信,服务器端也脱去被动的角色,可以向客户端主动发出信息
- 通过Http协议建立连接,升级为Websocket协议之后,依托于Tcp协议进行通信
- 直到客户端发出断开连接,连接生命周期才结束
------------------------------------------
| Websocket |
------------------------------------------
---------- ----------
| Client | | Server |
---------- ----------
| Hand Shake |
| ---------------------> | ||
| Acknowledgement | ||
| <--------------------- | ||
| | ||
| <--------------------> | ||
| Bi-dirictional message | ||
| <--------------------> | ||
| Connection end | ||
| <--------------------> | ||
| |
* || Connect lifecycle
Websocket 请求报文
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket //-->需要请求升级为Websocket报文
Connection: Upgrade //-->升级连接
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
Websocket 使用示例
Websocket网页客户端,Springboot服务器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
@Component
@ServerEndpoint("/webSocket")
public class WebSocket {
private Session session;
private static CopyOnWriteArraySet<WebSocket> webSockets=new CopyOnWriteArraySet<>();
@OnOpen
public void onOpen(Session session){
this.session=session;
webSockets.add(this);
System.out.println("有新的连接,总数"+webSockets.size());
}
@OnClose
public void onClose(){
webSockets.remove(this);
System.out.println("有新的断开,总数"+webSockets.size());
}
@OnMessage
public void onMessage(String message){
System.out.println(message);
send(message);
}
public void send(String message){
for (WebSocket webSocket:webSockets){
try {
webSocket.session.getBasicRemote().sendText(message);
}catch (Exception e){
e.printStackTrace();
}
}
}
}
- 具体实现工程:git@github.com:bijian127/WebsocketTest.git
Springboot后台作为客户端,向其他有Websocket服务后台订阅消息
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.3.9</version>
</dependency>
- Service具体实现过程
- 重写类继承于WebSocketClient
- 重写函数
public class ControllerWebsocket extends WebSocketClient {
private Logger logger = LoggerFactory.getLogger(this.getClass());
public ControllerWebsocket(URI serverUri) {
super(serverUri);
}
@Override
public void onOpen(ServerHandshake serverHandshake) {
logger.info("[Websocketclint] Connected.");
}
@Override
public void onMessage(String message) {
logger.info("[Websocketclient] ReceiveMessage->" + message);
}
@Override
public void onClose(int i, String s, boolean b) {
logger.info("[Websocketclient] Closed->" + i + "--" + s + "--" + b);
}
@Override
public void onError(Exception e) {
logger.error("[Websocketclient] Error:-->" + e);
}
}