WebSocketFrame
WebSocketFrame 是 Netty 中用于表示 WebSocket 消息帧的抽象基类,封装了帧的内容、分片标志和扩展位信息,供各类具体帧(如文本、二进制、控制帧)继承使用。
public abstract class WebSocketFrame extends BufferHolder<WebSocketFrame> {
// 表示是否是当前 WebSocket 消息的最后一个分片(frame)。
private final boolean finalFragment;
// 表示 RSV1/RSV2/RSV3 位(协议保留字段),通常用于 WebSocket 扩展(如压缩、加密扩展等)。
private final int rsv;
protected WebSocketFrame(Buffer binaryData) {
this(true, 0, binaryData);
}
protected WebSocketFrame(Send<Buffer> binaryData) {
super(binaryData);
finalFragment = true;
rsv = 0;
}
protected WebSocketFrame(boolean finalFragment, int rsv, Buffer binaryData) {
super(binaryData);
this.finalFragment = finalFragment;
this.rsv = rsv;
}
protected WebSocketFrame(WebSocketFrame copyFrom, Buffer binaryData) {
super(binaryData);
finalFragment = copyFrom.finalFragment;
rsv = copyFrom.rsv;
}
// 标识当前帧是否是消息的最后一部分(WebSocket 支持帧分片)
public boolean isFinalFragment() {
return finalFragment;
}
// 返回 RSV(Reserved Bits),可用于判断是否启用 WebSocket 扩展,如压缩 (permessage-deflate)
public int rsv() {
return rsv;
}
public Buffer binaryData() {
return getBuffer();
}
@Override
public String toString() {
return StringUtil.simpleClassName(this) + "(data: " + getBuffer().toString(defaultCharset()) + ')';
}
}
PingWebSocketFrame
PingWebSocketFrame
是 Netty 中表示 WebSocket Ping 控制帧的类,用于发送心跳检测数据,继承自 WebSocketFrame
并实现帧复制逻辑。
public class PingWebSocketFrame extends WebSocketFrame {
public PingWebSocketFrame(Buffer binaryData) {
super(binaryData);
}
public PingWebSocketFrame(boolean finalFragment, int rsv, Buffer binaryData) {
super(finalFragment, rsv, binaryData);
}
private PingWebSocketFrame(PingWebSocketFrame copyFrom, Buffer data) {
super(copyFrom, data);
}
@Override
protected WebSocketFrame receive(Buffer buf) {
return new PingWebSocketFrame(this, buf);
}
}
PongWebSocketFrame
PongWebSocketFrame
是 Netty 中用于响应 Ping
控制帧的 WebSocket Pong
帧实现,继承自 WebSocketFrame
,支持数据内容和帧复制功能。
public class PongWebSocketFrame extends WebSocketFrame {
public PongWebSocketFrame(Buffer binaryData) {
super(binaryData);
}
public PongWebSocketFrame(Send<Buffer> binaryData) {
super(binaryData);
}
public PongWebSocketFrame(boolean finalFragment, int rsv, Buffer binaryData) {
super(finalFragment, rsv, binaryData);
}
private PongWebSocketFrame(PongWebSocketFrame copyFrom, Buffer data) {
super(copyFrom, data);
}
@Override
protected WebSocketFrame receive(Buffer buf) {
return new PongWebSocketFrame(this, buf);
}
}
BinaryWebSocketFrame
BinaryWebSocketFrame
是 Netty 中用于传输二进制数据的 WebSocket 数据帧,支持设置是否为最后一帧以及协议扩展位。
public class BinaryWebSocketFrame extends WebSocketFrame {
public BinaryWebSocketFrame(Buffer binaryData) {
super(binaryData);
}
public BinaryWebSocketFrame(boolean finalFragment, int rsv, Buffer binaryData) {
super(finalFragment, rsv, binaryData);
}
private BinaryWebSocketFrame(BinaryWebSocketFrame copyFrom, Buffer data) {
super(copyFrom, data);
}
@Override
protected WebSocketFrame receive(Buffer buf) {
return new BinaryWebSocketFrame(this, buf);
}
}
TextWebSocketFrame
TextWebSocketFrame
是 Netty 中用于传输 UTF-8 编码文本的 WebSocket 数据帧,支持字符串构造、扩展位设置以及是否为最后一帧的标识。
public class TextWebSocketFrame extends WebSocketFrame {
public TextWebSocketFrame(BufferAllocator allocator, String text) {
super(fromText(allocator, text));
}
public TextWebSocketFrame(Buffer binaryData) {
super(binaryData);
}
public TextWebSocketFrame(BufferAllocator allocator, boolean finalFragment, int rsv, String text) {
super(finalFragment, rsv, fromText(allocator, text));
}
private TextWebSocketFrame(TextWebSocketFrame copyFrom, Buffer data) {
super(copyFrom, data);
}
private static Buffer fromText(BufferAllocator allocator, String text) {
if (text == null || text.isEmpty()) {
return allocator.allocate(0);
} else {
return allocator.copyOf(text, UTF_8);
}
}
public TextWebSocketFrame(boolean finalFragment, int rsv, Buffer binaryData) {
super(finalFragment, rsv, binaryData);
}
/**
* Returns the text data in this frame.
*/
public String text() {
return binaryData().toString(UTF_8);
}
@Override
protected WebSocketFrame receive(Buffer buf) {
return new TextWebSocketFrame(this, buf);
}
}
ContinuationWebSocketFrame
ContinuationWebSocketFrame
是用于 WebSocket 消息分片场景的续帧类型,可承载文本或二进制数据,支持设置是否为最终帧和协议扩展位。
public class ContinuationWebSocketFrame extends WebSocketFrame {
public ContinuationWebSocketFrame(Buffer binaryData) {
super(binaryData);
}
public ContinuationWebSocketFrame(boolean finalFragment, int rsv, Buffer binaryData) {
super(finalFragment, rsv, binaryData);
}
public ContinuationWebSocketFrame(BufferAllocator allocator, boolean finalFragment, int rsv, String text) {
this(finalFragment, rsv, fromText(allocator, text));
}
private ContinuationWebSocketFrame(ContinuationWebSocketFrame copyFrom, Buffer data) {
super(copyFrom, data);
}
public String text() {
return binaryData().toString(StandardCharsets.UTF_8);
}
private static Buffer fromText(BufferAllocator allocator, String text) {
if (text == null || text.isEmpty()) {
return allocator.allocate(0);
} else {
return allocator.copyOf(text.getBytes(StandardCharsets.UTF_8));
}
}
@Override
protected WebSocketFrame receive(Buffer buf) {
return new ContinuationWebSocketFrame(this, buf);
}
}
CloseWebSocketFrame
CloseWebSocketFrame
表示 WebSocket 连接关闭帧,包含关闭状态码和可选的关闭原因,用于优雅地关闭连接。
public class CloseWebSocketFrame extends WebSocketFrame {
public CloseWebSocketFrame(BufferAllocator allocator, WebSocketCloseStatus status) {
this(allocator, requireValidStatusCode(status.code()), status.reasonText());
}
public CloseWebSocketFrame(BufferAllocator allocator, WebSocketCloseStatus status, String reasonText) {
this(allocator, requireValidStatusCode(status.code()), reasonText);
}
public CloseWebSocketFrame(BufferAllocator allocator, int statusCode, String reasonText) {
this(allocator, true, 0, requireValidStatusCode(statusCode), reasonText);
}
public CloseWebSocketFrame(BufferAllocator allocator, boolean finalFragment, int rsv) {
this(finalFragment, rsv, allocator.allocate(0));
}
public CloseWebSocketFrame(BufferAllocator allocator, boolean finalFragment, int rsv, int statusCode, String reasonText) {
super(finalFragment, rsv, newBinaryData(allocator, requireValidStatusCode(statusCode), reasonText));
}
public CloseWebSocketFrame(boolean finalFragment, int rsv, Buffer binaryData) {
super(finalFragment, rsv, binaryData);
}
private CloseWebSocketFrame(CloseWebSocketFrame copyFrom, Buffer data) {
super(copyFrom, data);
}
// 构造符合 WebSocket Close 帧格式的二进制数据,包含状态码和 UTF-8 编码的关闭原因文本。
private static Buffer newBinaryData(BufferAllocator allocator, short statusCode, String reasonText) {
if (reasonText == null) {
reasonText = StringUtil.EMPTY_STRING;
}
final Buffer binaryData;
if (!reasonText.isEmpty()) {
byte[] reasonTextBytes = reasonText.getBytes(StandardCharsets.UTF_8);
binaryData = allocator.allocate(2 + reasonTextBytes.length);
binaryData.writeShort(statusCode);
binaryData.writeBytes(reasonTextBytes);
} else {
binaryData = allocator.allocate(2).writeShort(statusCode);
}
return binaryData;
}
public int statusCode() {
Buffer binaryData = binaryData();
if (binaryData == null || binaryData.readableBytes() < 2) {
return -1;
}
return binaryData.getUnsignedShort(binaryData.readerOffset());
}
public String reasonText() {
Buffer binaryData = binaryData();
if (binaryData == null || binaryData.readableBytes() <= 2) {
return "";
}
int base = binaryData.readerOffset();
try {
binaryData.skipReadableBytes(2);
return binaryData.toString(StandardCharsets.UTF_8);
} finally {
binaryData.readerOffset(base);
}
}
@Override
protected WebSocketFrame receive(Buffer buf) {
return new CloseWebSocketFrame(this, buf);
}
static short requireValidStatusCode(int statusCode) {
if (WebSocketCloseStatus.isValidStatusCode(statusCode)) {
return (short) statusCode;
} else {
throw new IllegalArgumentException(
"WebSocket close status code does NOT comply with RFC-6455: " + statusCode);
}
}
}