zoukankan      html  css  js  c++  java
  • 在线聊天室的实现(2)--基于Netty 4.x的Echo服务器实现

    前言:
      就如前文所讲述的, 聊天室往往是最基本的网络编程的学习案例. 本文以WebSocket为底层协议, 实现一个简单的基于web客户端的Echo服务.
      服务器采用Netty 4.x来实现, 源于其对websocket的超强支持, 基于卓越的性能和稳定.
      本系列的文章链接如下:
      1). websocket协议和javascript版的api 

    要点提示:
      Netty作为高性能网络编程框架, 其所有的网络IO操作皆为异步方式驱动. 而其核心的概念之一: ChannelHandler. 由一组ChannelHandler构成了ChannelPipeline, 决定了其编解码(Codec)/数据流(DataFlow)/业务处理(Logic Handler)的具体行为.
      ChannelHanlder的自由组合和清晰的职责划分, 让Netty更加的灵活和重要.

      
      WebSocket协议包括握手数据传输这两个阶段. 前者的握手是基于HTTP/HTTPS协议的, 而后者的数据传输则基于TCP的双向通讯模式. 数据以Frame的方式来组织和交互.
      本文不是Netty的学习文章, 这边就略为带过, 具体见后边的解释代码.

    服务端:
      基于之上的要点提要, 我们迅速来进行服务端的代码编写.
      使用netty 4.x版本, 其maven的依赖配置如下:

            <dependency>
                <groupId>io.netty</groupId>
                <artifactId>netty-all</artifactId>
                <version>4.0.29.Final</version>
            </dependency>
    

      服务端的代码如下:

    EventLoopGroup bossGroup = new NioEventLoopGroup();
    EventLoopGroup workerGroup = new NioEventLoopGroup();
    
    try {
      ServerBootstrap serverBootstrap = new ServerBootstrap();
    
      serverBootstrap.group(bossGroup, workerGroup)
        .channel(NioServerSocketChannel.class)
        .childHandler(new ChannelInitializer<SocketChannel>() {
          @Override
          protected void initChannel(SocketChannel socketChannel) throws Exception {
            // pipeline的设置, 参看下面
          }
        });
    
      ChannelFuture f = serverBootstrap.bind(8123).sync();
      f.channel().closeFuture().sync();
    } finally {
      bossGroup.shutdownGracefully();
      workerGroup.shutdownGracefully();
    }

      注: 这边是主体的服务器配置和启动代码, 其一如既然的简洁.
      核心的pipeline设置代码如下所示:

    ChannelPipeline cp = socketChannel.pipeline();
    // *) 支持http协议的解析
    cp.addLast(new HttpServerCodec());
    cp.addLast(new HttpObjectAggregator(65535));
    // *) 对于大文件支持 chunked方式写
    cp.addLast(new ChunkedWriteHandler());
    // *) 对websocket协议的处理--握手处理, ping/pong心跳, 关闭
    cp.addLast(new WebSocketServerProtocolHandler("/echoserver"));
    // *) 对TextWebSocketFrame的处理
    cp.addLast(new SimpleChannelInboundHandler<TextWebSocketFrame>() {
      @Override
      protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        // *) echo 逻辑
        ctx.writeAndFlush(new TextWebSocketFrame(msg.text()));
      }
    });
    

      注: HttpServerCodec和HttpObjectAggregator已经帮我们封装好了WebSocket的握手FullHttpRequest/FullHttpResponse包和各类数据Frame包. WebSocketServerProtocolHandler隐藏了握手的细节处理, 以及心跳处理和关闭响应. 多个ChannelHanlder的叠加和WebSocket协议本身的复杂是密切先关的.

    客户端:
      这边只是个演示项目, 因此尽量简洁地去实现.

    <div style="margin:0 auto;  800px;">
      <textarea id="taMessages" style=" 360px; height: 200px;" readonly ></textarea>
      <br />
      <input id="btnMessage" type="text" style="float:left; 300px;" />
      <input id="btnSend" type="button" value="Send" disabled="disabled" onclick="sendMessage();"/>
    </div>
    
    <script>
      /* 注意浏览器js的执行顺序 */
      var wsServer = 'ws://localhost:8123/echoserver'; //服务器地址
      var websocket = new WebSocket(wsServer); //创建WebSocket对象
    
      websocket.onopen = function(evt) {
        document.getElementById("btnSend").disabled = false;
      }
      websocket.onmessage = function(evt) {
        document.getElementById("taMessages").value += evt.data;
      }
      websocket.onclose = function(evt) {
      }
      websocket.onerror = function(evt) {
      }
    
      function sendMessage() {
        var message = document.getElementById('btnMessage').value;
        if ( websocket.readyState == WebSocket.OPEN ) {
          websocket.send(message);
        }
        document.getElementById('btnMessage').value = '';
      }
    </script>

      注: 发送数据到服务端, 然后把服务端返回的数据追加到文本区域中.

    效果:
      在chrome浏览器中, 效果如下:
      
      点击send按钮后, 经服务器返回其消息.
      
      消息在大文本区域中展示. 看来Echo服务一切正常.
      其实这是个悲伤的故事, 你觉得呢?

    写在最后:
      
    如果你觉得这篇文章对你有帮助, 请小小打赏下. 其实我想试试, 看看写博客能否给自己带来一点小小的收益. 无论多少, 都是对楼主一种由衷的肯定.

       

  • 相关阅读:
    php设计模式-工厂模式(一)
    php Pthread 线程 互斥锁
    php Pthread 多线程 Worker
    PHP多进程实例
    C# this 关键字
    .NET FileStream文件流,StreamReader文本流,MemoryStream内存流几种流的实例
    深入理解Static关键字修饰符
    SQL Server 视图
    .NET初识委托
    RSA加密
  • 原文地址:https://www.cnblogs.com/mumuxinfei/p/4682786.html
Copyright © 2011-2022 走看看