• netty整合websocket(完美教程)


    websocket的介绍:

    WebSocket是一种在网络通信中的协议,它是独立于HTTP协议的。该协议基于TCP/IP协议,可以提供双向通讯并保有状态。这意味着客户端和服务器可以进行实时响应,并且这种响应是双向的。WebSocket协议端口通常是80,443。

    WebSocket的出现使得浏览器具备了实时双向通信的能力。与HTTP这种非持久单向响应应答的协议相比,WebSocket是一个持久化的协议。举例来说,即使在关闭网页或者浏览器后,WebSocket的连接仍然保持,用户也可以继续接收到服务器的消息。

    此外,要建立WebSocket连接,需要浏览器和服务器握手进行建立连接。一旦连接建立,WebSocket可以在浏览器和服务器之间双向发送或接受信息。总的来说,WebSocket提供了一个高效、实时的双向通信方案。

    1、用netty构建websocket服务器

    1. package org.tianfan.websocket;// WebSocketServer.java
    2. import io.netty.bootstrap.ServerBootstrap;
    3. import io.netty.channel.ChannelFuture;
    4. import io.netty.channel.ChannelInitializer;
    5. import io.netty.channel.ChannelPipeline;
    6. import io.netty.channel.EventLoopGroup;
    7. import io.netty.channel.nio.NioEventLoopGroup;
    8. import io.netty.channel.socket.SocketChannel;
    9. import io.netty.channel.socket.nio.NioServerSocketChannel;
    10. import io.netty.handler.codec.http.HttpObjectAggregator;
    11. import io.netty.handler.codec.http.HttpServerCodec;
    12. import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
    13. public class WebSocketServer {
    14. private final int port;
    15. public WebSocketServer(int port) {
    16. this.port = port;
    17. }
    18. public void run() throws Exception {
    19. EventLoopGroup bossGroup = new NioEventLoopGroup();
    20. EventLoopGroup workerGroup = new NioEventLoopGroup();
    21. try {
    22. ServerBootstrap b = new ServerBootstrap();
    23. b.group(bossGroup, workerGroup)
    24. .channel(NioServerSocketChannel.class)
    25. .childHandler(new ChannelInitializer() {
    26. @Override
    27. public void initChannel(SocketChannel ch) throws Exception {
    28. ChannelPipeline p = ch.pipeline();
    29. p.addLast(new HttpServerCodec());
    30. p.addLast(new HttpObjectAggregator(65536));
    31. p.addLast(new WebSocketServerProtocolHandler("/websocket"));
    32. p.addLast(new WebSocketServerHandler());
    33. }
    34. });
    35. ChannelFuture f = b.bind(port).sync();
    36. f.channel().closeFuture().sync();
    37. } finally {
    38. workerGroup.shutdownGracefully();
    39. bossGroup.shutdownGracefully();
    40. }
    41. }
    42. public static void main(String[] args) throws Exception {
    43. int port = 8080;
    44. if (args.length > 0) {
    45. port = Integer.parseInt(args[0]);
    46. }
    47. new WebSocketServer(port).run();
    48. }
    49. }

    我来解释一下上面的代码:

    • p.addLast(new HttpServerCodec()):添加HTTP服务器编解码器,用于将数据转换成HTTP协议格式进行传输。
    • p.addLast(new HttpObjectAggregator(65536)):添加HTTP对象聚合处理器,用于将HTTP请求或响应中的多个消息片段聚合成完整的消息。
    • p.addLast(new WebSocketServerProtocolHandler("/websocket")):添加WebSocket协议处理器,用于处理WebSocket握手、消息传输等操作。
    • p.addLast(new WebSocketServerHandler()):添加WebSocket处理器,用于处理客户端与服务器端之间的数据交换,实现自定义的业务逻辑。

    使用Netty框架中的WebSocketServerProtocolHandler处理器,将HTTP升级为WebSocket协议。它创建了一个新的管道(pipeline)并将WebSocket处理程序添加到管道的尾部,以便处理WebSocket协议的握手和帧。"/websocket"是WebSocket的URI路径,它指定了WebSocket服务的相对地址,该地址将在客户端请求连接时被指定。

    1. package org.tianfan.websocket;
    2. import io.netty.channel.ChannelHandlerContext;
    3. import io.netty.channel.SimpleChannelInboundHandler;
    4. import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
    5. public class WebSocketServerHandler extends SimpleChannelInboundHandler {
    6. @Override
    7. public void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
    8. // 处理消息
    9. System.out.println("Received message: " + msg.text());
    10. ctx.channel().writeAndFlush(new TextWebSocketFrame("Server received: " + msg.text()));
    11. }
    12. @Override
    13. public void channelActive(ChannelHandlerContext ctx) throws Exception {
    14. // 添加连接
    15. System.out.println("Client connected: " + ctx.channel());
    16. }
    17. @Override
    18. public void channelInactive(ChannelHandlerContext ctx) throws Exception {
    19. // 断开连接
    20. System.out.println("Client disconnected: " + ctx.channel());
    21. }
    22. @Override
    23. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    24. // 异常处理
    25. cause.printStackTrace();
    26. ctx.close();
    27. }
    28. }

    我来解释一下上面的代码:

    刚信息发过来的时候,在服务端打印,并写入前端。

    2、前端客户端页面:

    1. <!-- index.html -->
    2. <!DOCTYPE html>
    3. <html>
    4. <head>
    5. <meta charset="UTF-8">
    6. <title>WebSocket Test</title>
    7. </head>
    8. <body>
    9. <h1>WebSocket Test</h1>
    10. <div>
    11. <input type="text" id="message" placeholder="Message">
    12. <button onclick="send()">Send</button>
    13. </div>
    14. <div id="output"></div>
    15. <script>
    16. var socket = new WebSocket("ws://localhost:8080/websocket");
    17. socket.onopen = function(event) {
    18. console.log("WebSocket opened: " + event);
    19. };
    20. socket.onmessage = function(event) {
    21. console.log("WebSocket message received: " + event.data);
    22. var output = document.getElementById("output");
    23. output.innerHTML += "

      " + event.data + "

      "
      ;
    24. };
    25. socket.onclose = function(event) {
    26. console.log("WebSocket closed: " + event);
    27. };
    28. function send() {
    29. var message = document.getElementById("message").value;
    30. socket.send(message);
    31. }
    32. </script>
    33. </body>
    34. </html>

    运行结果:

  • 相关阅读:
    二分查找详解(while条件判断+转换值判断)
    AtCoder Beginner Contest 278 G.Generalized Subtraction Game(思维题/博弈 multi-sg)
    SpringCloud-Rest微服务工程的构建
    nodejs+vue+ElementUi废品废弃资源回收系统
    Mac | Vmware Fusion | 分辨率自动还原问题解决
    Lock和synchronized的区别
    CSS选择器
    Go十大常见错误第9篇:使用文件名称作为函数输入
    在有序数组中插入一个数
    【每日一题】 Dijkstra求最短路 II,堆优化算法
  • 原文地址:https://blog.csdn.net/m0_63251896/article/details/134518001