基于WebSocket协议的Netty开发

WebSocket是一种在单个TCP连接上进行全双工通信的协议。在这篇博客中,我们将使用Netty开发一个基于WebSocket协议的实时聊天系统。

1. 环境准备

首先,我们需要在项目中引入Netty的依赖。在Maven项目中,添加以下依赖:

1
2
3
4
5
<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.1.65.Final</version>
</dependency>

2. WebSocket服务器开发

2.1 创建WebSocketHandler

首先,我们需要创建一个处理WebSocket通信的Handler。这里我们自定义一个WebSocketHandler,用于处理客户端的消息:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class WebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        // 连接建立时发送欢迎消息
        ctx.channel().writeAndFlush(new TextWebSocketFrame("欢迎连接WebSocket服务器!"));
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        // 接收客户端消息并广播
        String text = msg.text();
        System.out.println("收到客户端消息:" + text);

        // 遍历所有连接的Channel
        for (Channel channel : ctx.channel().parent().children()) {
            // 广播消息
            if (channel != ctx.channel()) {
                channel.writeAndFlush(new TextWebSocketFrame(text));
            } else {
                channel.writeAndFlush(new TextWebSocketFrame("自己:" + text));
            }
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}

在这个WebSocketHandler中,我们重写了handlerAdded方法,用于在连接建立时发送欢迎消息。重写了channelRead0方法,用于接收客户端的消息并广播给所有连接的客户端。

2.2 创建WebSocketServer

接下来,我们创建一个WebSocket服务器,绑定端口并启动:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class WebSocketServer {

    public static void main(String[] args) throws Exception {
        // 创建EventLoopGroup
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            // 创建ServerBootstrap
            ServerBootstrap bootstrap = new ServerBootstrap();

            // 设置参数
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            // 添加WebSocketHandler前的编码解码器
                            ch.pipeline().addLast(new HttpServerCodec());
                            ch.pipeline().addLast(new HttpObjectAggregator(65536));
                            ch.pipeline().addLast(new WebSocketServerProtocolHandler("/websocket"));
                            // 添加WebSocketHandler
                            ch.pipeline().addLast(new WebSocketHandler());
                        }
                    })
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);

            // 绑定端口并启动
            ChannelFuture future = bootstrap.bind(8080).sync();

            // 等待服务器关闭
            future.channel().closeFuture().sync();
        } finally {
            // 释放资源
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

在这个WebSocketServer中,我们创建了两个EventLoopGroup用于处理客户端连接和IO操作,然后创建了一个ServerBootstrap,设置了相关参数,并添加了我们之前创建的WebSocketHandler。在添加WebSocketHandler之前,我们还添加了一些编码解码器,用于处理WebSocket通信。最后,我们绑定了8080端口并启动了服务器。

3. WebSocket客户端开发

接下来,我们使用JavaScript开发一个简单的WebSocket客户端,用于连接我们的WebSocket服务器并进行实时聊天。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebSocket客户端</title>
</head>
<body>
    <input type="text" id="message" placeholder="请输入消息">
    <button onclick="sendMessage()">发送</button>
    <div id="content"></div>

    <script>
        // 创建WebSocket连接
        const socket = new WebSocket("ws://localhost:8080/websocket");

        // 连接成功时的回调函数
        socket.onopen = function () {
            console.log("连接成功");
        };

        // 接收服务器消息时的回调函数
        socket.onmessage = function (event) {
            const content = document.getElementById("content");
            content.innerHTML += "<p>" + event.data + "</p>";
        };

        // 发送消息
        function sendMessage() {
            const message = document.getElementById("message").value;
            socket.send(message);
        }
    </script>
</body>
</html>

在这个WebSocket客户端中,我们创建了一个WebSocket连接,并设置了连接成功和接收服务器消息时的回调函数。在发送消息时,我们获取输入框中的消息并通过WebSocket连接发送给服务器。

4. 测试

现在,我们可以使用浏览器打开我们的WebSocket客户端,连接我们的WebSocket服务器,并进行实时聊天了。

5. 总结

在这篇博客中,我们使用Netty开发了一个基于WebSocket协议的实时聊天系统。通过创建WebSocketHandler处理客户端消息,并创建WebSocketServer绑定端口并启动,我们实现了一个可以进行实时通信的WebSocket服务器。同时,我们还使用JavaScript开发了一个简单的WebSocket客户端,用于连接我们的WebSocket服务器并进行实时聊天。当然,这只是一个简单的示例,实际开发中可能需要处理更复杂的情景,但这个示例已经展示了基于WebSocket协议的Netty开发的基本思路。