从零学Netty(八)Netty实现WebSocket服务器

我就是我 2022-12-15 03:55 438阅读 0赞

简介

  • WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议
  • WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据
  • 浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输
  • HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDQ2MTI4MQ_size_16_color_FFFFFF_t_70

WebSocket 属性












Socket.readyState

只读属性 readyState 表示连接状态,可以是以下值:



  • 0 - 表示连接尚未建立。


  • 1 - 表示连接已建立,可以进行通信。


  • 2 - 表示连接正在进行关闭。


  • 3 - 表示连接已经关闭或者连接不能打开。


Socket.bufferedAmount

只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。

WebSocket 事件
























open Socket.onopen 连接建立时触发
message Socket.onmessage 客户端接收服务端数据时触发
error Socket.onerror 通信发生错误时触发
close Socket.onclose 连接关闭时触发

WebSocket 方法












Socket.send()

使用连接发送数据

Socket.close()

关闭连接

实例demo

Netty使用WebSocket协议实现服务器

  1. /**
  2. * ws服务器
  3. *
  4. * @author LionLi
  5. */
  6. public class WebSocketServer {
  7. public static void main(String[] args) throws Exception {
  8. // 创建 boss 和 worker 工作组
  9. EventLoopGroup bossGroup = new NioEventLoopGroup(1);
  10. EventLoopGroup workerGroup = new NioEventLoopGroup();
  11. try {
  12. ServerBootstrap serverBootstrap = new ServerBootstrap();
  13. serverBootstrap.group(bossGroup, workerGroup);
  14. // 主线程处理
  15. serverBootstrap.channel(NioServerSocketChannel.class);
  16. // 子线程业务处理
  17. serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
  18. @Override
  19. protected void initChannel(SocketChannel ch) {
  20. ChannelPipeline pipeline = ch.pipeline();
  21. //因为基于http协议,使用http的编码和解码器
  22. pipeline.addLast(new HttpServerCodec());
  23. //是以块方式写,添加ChunkedWriteHandler处理器
  24. pipeline.addLast(new ChunkedWriteHandler());
  25. // http数据聚合器 用于将大数据量分段传输的数据 聚合
  26. pipeline.addLast(new HttpObjectAggregator(8192));
  27. // websocket协议处理器
  28. pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
  29. // 自定义的业务处理
  30. pipeline.addLast(new WebSocketHandler());
  31. }
  32. });
  33. // 启动服务器
  34. ChannelFuture channelFuture = serverBootstrap.bind(8088).sync();
  35. channelFuture.channel().closeFuture().sync();
  36. } finally {
  37. bossGroup.shutdownGracefully();
  38. workerGroup.shutdownGracefully();
  39. }
  40. }
  41. }

自定义业务处理

  1. /**
  2. * 业务处理器
  3. *
  4. * @author LionLi
  5. */
  6. // TextWebSocketFrame 文本处理
  7. public class WebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
  8. /**
  9. * 通道消息读取
  10. */
  11. @Override
  12. protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) {
  13. System.out.println("收到消息 " + msg.text());
  14. ctx.channel().writeAndFlush(new TextWebSocketFrame("收到消息 " + msg.text()));
  15. }
  16. /**
  17. * 连接初始化
  18. */
  19. @Override
  20. public void handlerAdded(ChannelHandlerContext ctx) {
  21. System.out.println("客户端连接:通道唯一id为 => " + ctx.channel().id().asLongText());
  22. System.out.println("客户端连接:通道不唯一id为 => " + ctx.channel().id().asShortText());
  23. }
  24. /**
  25. * 退出连接
  26. */
  27. @Override
  28. public void handlerRemoved(ChannelHandlerContext ctx) {
  29. System.out.println("客户端断开" + ctx.channel().id().asLongText());
  30. }
  31. /**
  32. * 异常处理
  33. */
  34. @Override
  35. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
  36. System.out.println("客户端异常 " + cause.getMessage());
  37. //关闭连接
  38. ctx.close();
  39. }
  40. }

测试

使用页面进行测试

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Netty实现WebSocket服务器</title>
  6. </head>
  7. <body>
  8. <script>
  9. var socket;
  10. // 判断当前浏览器是否支持websocket
  11. if (window.WebSocket) {
  12. // 创建连接
  13. socket = new WebSocket("ws://localhost:8088/ws");
  14. // 消息监听
  15. socket.onmessage = function (ev) {
  16. var rt = document.getElementById("responseText");
  17. rt.value = rt.value + "\n" + ev.data;
  18. }
  19. // 连接初始化
  20. socket.onopen = function (ev) {
  21. var rt = document.getElementById("responseText");
  22. rt.value = "连接开启了.."
  23. }
  24. // 连接关闭
  25. socket.onclose = function (ev) {
  26. var rt = document.getElementById("responseText");
  27. rt.value = rt.value + "\n" + "连接关闭了.."
  28. }
  29. } else {
  30. alert("当前浏览器不支持websocket")
  31. }
  32. // 发送消息
  33. function send(message) {
  34. if (!window.socket) {
  35. return;
  36. }
  37. if (socket.readyState === WebSocket.OPEN) {
  38. socket.send(message)
  39. } else {
  40. alert("连接没有开启");
  41. }
  42. }
  43. </script>
  44. <form onsubmit="return false">
  45. <label>
  46. <textarea name="message" style="height: 300px; width: 300px"></textarea>
  47. </label>
  48. <input type="button" value="发送消息" onclick="send(this.form.message.value)">
  49. <label for="responseText"></label>
  50. <textarea id="responseText" style="height: 300px; width: 300px"></textarea>
  51. <input type="button" value="清空内容" onclick="document.getElementById('responseText').value=''">
  52. </form>
  53. </body>
  54. </html>

启动服务器

2020101515334966.png

打开页面 自动连接服务器

2020101515341579.png

20201015153534239.png

发送消息

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDQ2MTI4MQ_size_16_color_FFFFFF_t_70 1

20201015153558777.png

关闭页面

20201015153617902.png

项目已上传到gitee

地址: netty-demo

如果帮到您了,请帮忙点个star

发表评论

表情:
评论列表 (有 0 条评论,438人围观)

还没有评论,来说两句吧...

相关阅读

    相关 开始netty

    Netty概述: 1、netty是基于Java NIO的网络应用框架,client-server框架 2、Netty是一个高性能、异步事件驱动的NIO框架,它提供了对T