以下是一个使用Netty框架实现WebSocket服务器的简单代码示例:
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
public class WebSocketServer {
private static final int PORT = 8888;
public static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new HttpServerCodec());
ch.pipeline().addLast(new ChunkedWriteHandler());
ch.pipeline().addLast(new HttpObjectAggregator(65536));
ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws"));
ch.pipeline().addLast(new WebSocketServerHandler());
}
});
ChannelFuture f = b.bind(PORT).sync();
System.out.println("WebSocket server started on port " + PORT + '.');
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
}
同时,需要创建一个处理WebSocket消息的处理器类 WebSocketServerHandler
:
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
public class WebSocketServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
// 这里处理接收到的WebSocket消息
System.out.println("Received message: " + msg.text());
// 简单回复消息
ctx.writeAndFlush(new TextWebSocketFrame("You sent: " + msg.text()));
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
WebSocketServer
:
NioEventLoopGroup
,bossGroup
用于处理客户端的连接请求,workerGroup
用于处理连接建立后的读写操作。ServerBootstrap
配置服务器,指定了服务器通道类型为 NioServerSocketChannel
,并通过 childHandler
方法设置了每个新连接的通道初始化逻辑。HttpServerCodec
用于处理HTTP协议编解码,因为WebSocket是基于HTTP协议进行握手的。ChunkedWriteHandler
支持异步发送大的码流,而不会占用过多的内存。HttpObjectAggregator
用于将多个消息组装成完整的HTTP请求或响应,这里设置聚合的最大内容长度为65536字节。WebSocketServerProtocolHandler
用于处理WebSocket协议的握手过程,并将后续的WebSocket帧消息转发到后续的处理器,"/ws"
是WebSocket的路径。WebSocketServerHandler
是自定义的处理器,用于处理接收到的WebSocket消息。b.bind(PORT).sync()
绑定指定端口并启动服务器,最后通过 f.channel().closeFuture().sync()
等待服务器关闭。WebSocketServerHandler
:
channelRead0
方法用于处理接收到的 TextWebSocketFrame
类型的消息,这里只是简单打印接收到的消息,并回复一个包含原消息的新消息。exceptionCaught
方法在通道发生异常时被调用,用于打印异常堆栈信息并关闭通道。你可以运行 WebSocketServer
类,启动WebSocket服务器,然后使用支持WebSocket协议的客户端(如浏览器中的JavaScript WebSocket对象 、Postman等)连接到 ws://localhost:8888/ws
来测试服务器功能。
————————————————————————————————————
以下是在之前Netty实现WebSocket服务器的代码基础上,添加更丰富自定义消息处理逻辑的示例,实现根据客户端发送的不同指令,返回不同响应。
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
public class WebSocketServer {
private static final int PORT = 8888;
public static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new HttpServerCodec());
ch.pipeline().addLast(new ChunkedWriteHandler());
ch.pipeline().addLast(new HttpObjectAggregator(65536));
ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws"));
ch.pipeline().addLast(new WebSocketServerHandler());
}
});
ChannelFuture f = b.bind(PORT).sync();
System.out.println("WebSocket server started on port " + PORT + '.');
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
}
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
public class WebSocketServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
String receivedMessage = msg.text();
String responseMessage = handleMessage(receivedMessage);
ctx.writeAndFlush(new TextWebSocketFrame(responseMessage));
}
private String handleMessage(String message) {
// 简单的自定义消息处理逻辑,根据不同指令返回不同响应
if ("hello".equalsIgnoreCase(message)) {
return "Hello! Nice to meet you.";
} else if ("time".equalsIgnoreCase(message)) {
long currentTime = System.currentTimeMillis();
return "Current time is: " + currentTime;
} else {
return "Unrecognized command. Available commands: hello, time";
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
channelRead0
方法:当接收到客户端发送的 TextWebSocketFrame
消息时,先获取消息内容,然后调用 handleMessage
方法处理消息,根据处理结果生成响应消息,最后将响应消息写回给客户端。handleMessage
方法:这里实现了简单的自定义消息处理逻辑。当客户端发送的消息为 "hello"
时,返回问候语;当消息为 "time"
时,返回当前时间戳;对于其他不识别的消息,返回提示信息,告知客户端可用的指令。你可以运行 WebSocketServer
类启动服务器,然后使用支持WebSocket的客户端(如浏览器通过JavaScript的 WebSocket
对象,示例代码如下 )来测试不同消息指令的处理情况:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebSocket Testtitle>
head>
<body>
<script>
const socket = new WebSocket('ws://localhost:8888/ws');
socket.onopen = function (event) {
// 发送消息测试
socket.send('hello');
socket.send('time');
socket.send('unknown');
};
socket.onmessage = function (event) {
console.log('Received: ', event.data);
};
socket.onerror = function (error) {
console.log('Error: ', error);
};
socket.onclose = function (event) {
console.log('Connection closed');
};
script>
body>
html>
上述HTML页面通过JavaScript创建WebSocket连接,在连接建立后发送不同指令,并处理接收到的服务器响应消息。