1.什么是websocket?
1.WebSocket只有在建立握手连接的时候借用了HTTP协议,连接成功后的通信部分都是基于TCP的连接。
2.WebSocket连接服务器的URI以“ws”或者“wss”开头。ws开头的默认TCP端口为80,wss开头的默认端口为443。
3.协议分为两个部分: 握手阶段和全双工通信阶段。
2.WebSocket 的工作流程
握手阶段、数据传输阶段和关闭阶段
2.1握手阶段
Websocket协议的握手阶段是使用的HTTP协议。
1.客户端发送一个 HTTP GET 请求给服务器,请求头中包含了 Upgrade、Connection、Sec-WebSocket-Key 等字段,告诉服务器要升级到 WebSocket 协议。
GET /nickname11 HTTP/1.1
Host: 127.0.0.1:9090
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Key: wJdg8v4EJiDsIZg5+s0hY8RUQ2A=
Sec-WebSocket-Version: 13
Origin: http://127.0.0.1
2.响应头中包含了 Upgrade、Connection、Sec-WebSocket-Accept 等字段,告诉客户端已经成功升级到 WebSocket 协议。
HTTP/1.1 101 Switching Protocol
Upgrade: WebSocket
Sec-WebSocket-Version: 13
Connection: Upgrade
Sec-WebSocket-Accept: wJdg8v4EJiDsIZg5+s0hY8RUQ2A=
3.客户端和服务器之间的连接就在这个阶段建立。
2.2数据传输阶段
在数据传输阶段,客户端和服务器之间可以直接发送消息,不需要像 HTTP 协议那样每次都发送请求和响应。
1.客户端可以通过 WebSocket 对象的 send() 方法向服务器发送消息.
2.服务器可以通过 WebSocket 的 onmessage 事件监听客户端发送的消息,然后根据消息的内容进行相应的操作
3.客户端和服务器之间可以通过 WebSocket 对象的 close() 方法关闭连接,或者等待网络中断或其他原因自动断开连接。
2.3关闭阶段
1.客户端可以通过 WebSocket 对象的 close() 方法发送关闭消息给服务器
2.服务器可以通过 WebSocket 对象的 onclose 事件监听客户端发送的关闭消息,然后发送一条关闭消息给客户端。
3,客户端和服务器之间可以交替发送关闭消息,直到连接关闭为止。
3.WebSocket的优点
1.实时性好:WebSocket 可以实现实时交互和即时通信,对于在线游戏、聊天室、股票行情等实时性要求高的应用场景非常重要。
2.数据传输量小:HTTP长连接中,每次数据交换除了真正的数据部分外,服务器和客户端还要大量交换HTTP header,信息交换效率很低。Websocket协议通过第一个request建立了TCP连接之后,之后交换的数据都不需要发送 HTTP header就能交换数据。
3.双向通信:WebSocket 支持客户端和服务器之间的双向通信,客户端和服务器之间可以直接发送消息,不需要像 HTTP 协议那样每次都发送请求和响应。
4.长连接:WebSocket 的连接可以保持长时间,而不需要像 HTTP 协议那样在每次请求和响应之间重新建立连接。
4.JAVA如何用WebSocket?
1.引入jar包
<!-- 引入websocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2.服务端使用@ServerEndpoint注解标注当前类为一个 WebSocket 服务器,客户端可以通过ws://localhost:7777/webSocket/10086来连接到 WebSocket 服务器端。
@Component
@Slf4j
@ServerEndpoint("/websocket/{userId}")
public class WebSocketServer {
//与某个客户端的连接会话,需要通过它来给客户端发送数据
private Session session;
private static final CopyOnWriteArraySet<WebSocketServer> webSockets = new CopyOnWriteArraySet<>();
// 用来存在线连接数
private static final Map<String, Session> sessionPool = new HashMap<String, Session>();
/**
* 链接成功调用的方法
*/
@OnOpen
public void onOpen(Session session, @PathParam(value = "userId") String userId) {
try {
this.session = session;
webSockets.add(this);
sessionPool.put(userId, session);
log.info("websocket消息: 有新的连接,总数为:" + webSockets.size());
} catch (Exception e) {
}
}
/**
* 收到客户端消息后调用的方法
*/
@OnMessage
public void onMessage(String message) {
log.info("websocket消息: 收到客户端消息:" + message);
}
/**
* 此为单点消息
*/
public void sendOneMessage(String userId, String message) {
Session session = sessionPool.get(userId);
if (session != null && session.isOpen()) {
try {
log.info("websocket消: 单点消息:" + message);
session.getAsyncRemote().sendText(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
详情可以参考这篇文章:一步步教你如何使用Java实现WebSocket_java_脚本之家 (jb51.net)