用Netty实现的WebSocket服务器代码示例中添加自定义消息处理逻辑

一.

以下是一个使用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();
    }
}

代码说明:

  1. 主类 WebSocketServer
    • 线程组初始化:创建了两个 NioEventLoopGroupbossGroup 用于处理客户端的连接请求,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() 等待服务器关闭。
  2. 处理器类 WebSocketServerHandler
    • 消息处理channelRead0 方法用于处理接收到的 TextWebSocketFrame 类型的消息,这里只是简单打印接收到的消息,并回复一个包含原消息的新消息。
    • 异常处理exceptionCaught 方法在通道发生异常时被调用,用于打印异常堆栈信息并关闭通道。

你可以运行 WebSocketServer 类,启动WebSocket服务器,然后使用支持WebSocket协议的客户端(如浏览器中的JavaScript WebSocket对象 、Postman等)连接到 ws://localhost:8888/ws 来测试服务器功能。

————————————————————————————————————

二.

以下是在之前Netty实现WebSocket服务器的代码基础上,添加更丰富自定义消息处理逻辑的示例,实现根据客户端发送的不同指令,返回不同响应。

1. WebSocketServer类

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();
        }
    }
}

2. 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 {
        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();
    }
}

代码说明

  • WebSocketServer类:和之前示例一样,负责初始化Netty服务器,创建线程组,配置服务器通道和处理器等,启动并监听指定端口。
  • WebSocketServerHandler类
    • 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连接,在连接建立后发送不同指令,并处理接收到的服务器响应消息。

你可能感兴趣的:(websocket,服务器,网络协议)