1、HTTP 协议包含的较长的请求头,有效数据只占很少一部分,浪费带宽
2、短轮询频繁轮询对服务器压力较大,即使使用长轮询方案,客户端较多时仍会对客户端造成不小压力
// 客户端请求
GET ws://localhost:8888/ HTTP/1.1
Host: localhost:8888
Connection: Upgrade
Upgrade: websocket
Origin: http://localhost:63342
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,ja;q=0.8,en;q=0.7
Sec-WebSocket-Key: b7wpWuB9MCzOeQZg2O/yPg==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
// 服务端响应
HTTP/1.1 101 Web Socket Protocol Handshake
Connection: Upgrade
Date: Wed, 22 Nov 2023 08:15:00 GMT
Sec-WebSocket-Accept: Q4TEk+qOgJsKy7gedijA5AuUVIw=
Server: TooTallNate Java-WebSocket
Upgrade: websocket
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/64) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
| Extended payload length continued, if payload len == 127 |
+ - - - - - - - - - - - - - - - +-------------------------------+
| |Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------- - - - - - - - - - - - - - - - +
: Payload Data continued ... :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Payload Data continued ... |
+---------------------------------------------------------------+
WebSocket 定义了几种帧类型,其中最常见的是文本帧(Opcode 为 0x1)和二进制帧(Opcode 为 0x2)。其他帧类型包括连接关闭帧、Ping 帧、Pong 帧等。
Client: FIN=1, opcode=0x1, msg="hello"
Server: (process complete message immediately) Hi.
Client: FIN=0, opcode=0x1, msg="and a"
Server: (listening, newmessage containing text started)
Client: FIN=0, opcode=0x0, msg="happy new"
Server: (listening, payload concatenated to previous message)
Client: FIN=1, opcode=0x0, msg="year!"
Server: (process complete message) Happy new year to you too!
Client: FIN=1, opcode=0x8, msg="1000"
Server: FIN=1, opcode=0x8, msg="1000"
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebSocket Chattitle>
head>
<body>
<div id="chat">div>
<input type="text" id="messageInput" placeholder="Type your message">
<button onclick="sendMessage()">Sendbutton>
<script>
const socket = new WebSocket('ws://localhost:8888');
socket.onopen = (event) => {
console.log('WebSocket connection opened:', event);
};
socket.onmessage = (event) => {
const messageDiv = document.getElementById('chat');
const messageParagraph = document.createElement('p');
messageParagraph.textContent = event.data;
messageDiv.appendChild(messageParagraph);
};
socket.onclose = (event) => {
console.log('WebSocket connection closed:', event);
};
function sendMessage() {
const messageInput = document.getElementById('messageInput');
const message = messageInput.value;
socket.send(message);
messageInput.value = '';
}
script>
body>
html>
package chat;
import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
import java.net.InetSocketAddress;
public class ChatServer extends WebSocketServer {
public ChatServer(int port) {
super(new InetSocketAddress(port));
}
@Override
public void onOpen(WebSocket conn, ClientHandshake handshake) {
System.out.println("New connection from: " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
}
@Override
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
System.out.println("Closed connection to: " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
}
@Override
public void onMessage(WebSocket conn, String message) {
System.out.println("Received message: " + message);
// Broadcast the message to all connected clients
broadcast(message);
}
@Override
public void onError(WebSocket conn, Exception ex) {
System.err.println("Error on connection: " + ex.getMessage());
}
@Override
public void onStart() {
}
public static void main(String[] args) {
int port = 8888;
ChatServer server = new ChatServer(port);
server.start();
System.out.println("WebSocket Server started on port: " + port);
}
}
你好,我是 Lorin 洛林,一位 Java 后端技术开发者!座右铭:Technology has the power to make the world a better place.
我对技术的热情是我不断学习和分享的动力。我的博客是一个关于Java生态系统、后端开发和最新技术趋势的地方。
作为一个 Java 后端技术爱好者,我不仅热衷于探索语言的新特性和技术的深度,还热衷于分享我的见解和最佳实践。我相信知识的分享和社区合作可以帮助我们共同成长。
在我的博客上,你将找到关于Java核心概念、JVM 底层技术、常用框架如Spring和Mybatis 、MySQL等数据库管理、RabbitMQ、Rocketmq等消息中间件、性能优化等内容的深入文章。我也将分享一些编程技巧和解决问题的方法,以帮助你更好地掌握Java编程。
我鼓励互动和建立社区,因此请留下你的问题、建议或主题请求,让我知道你感兴趣的内容。此外,我将分享最新的互联网和技术资讯,以确保你与技术世界的最新发展保持联系。我期待与你一起在技术之路上前进,一起探讨技术世界的无限可能性。
保持关注我的博客,让我们共同追求技术卓越。