前言:
  就如前文所讲述的, 聊天室往往是最基本的网络编程的学习案例. 本文以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; width: 800px;">
  <textarea id="taMessages" style="width: 360px; height: 200px;" readonly ></textarea>
  <br />
  <input id="btnMessage" type="text" style="float:left; width: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服务一切正常.
  其实这是个悲伤的故事, 你觉得呢?

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

  

最新文章

  1. 最适合作为Java基础面试题之Singleton模式
  2. 人民币符号在html的显示方法
  3. uva 12169
  4. 在页面头部&lt;!DOCTYPE html ....&gt; 前面不能有任何输出
  5. LeetCode Binary Tree Level Order Traversal II (二叉树颠倒层序)
  6. iphone 屏幕投射到Mac上
  7. 《神经网络和深度学习》系列文章十二:Hadamard积,s⊙t
  8. Python3.5.1 下使用HTMLParser报错
  9. SDK Hello world(直接使用SDK封装)
  10. 使用EF扩展EntityFramework.BulkInsert实现批量插入
  11. webstorm安装与本地激活
  12. xhr.readyState就绪状态
  13. 使用http -server 搭建本地简易文件服务器
  14. Socket相关概念
  15. Mac下将文件复制到移动硬盘
  16. Vue-CLI和脚手架
  17. LeetCode(15. 三数之和)
  18. SpringBoot(十一):springboot2.0.2下配置mybatis generator环境,并自定义字段/getter/settetr注释
  19. Bash script set help function
  20. spring boot多模块项目找不到类

热门文章

  1. GZFramwork快速开发框架演练之会员系统(三)添加会员等级管理
  2. firefox阅读模式
  3. linux权限,所有者、所在组、其他组(其他人员),chmod,chown
  4. [HIHO1107]Shortest Proper Prefix(trie)
  5. 读《编写可维护的JavaScript》第一章总结
  6. python走起之第三话
  7. docker部署tomcat
  8. SQL语言增加、修改、删除数据的语法
  9. 获取sim卡序列号
  10. LINUX CP 跳过询问是否覆盖