首页 > 软件开发 > 基于netty的websocket开发小结

快速发布【软件开发】相关需求,专业顾问为您服务 快速发布

用此手机号发布,您还可以点击 更换

发布需求
请输入正确的手机号
请输入正确的验证码

您是不是要找:

  • 专家问诊,提供专业建议
  • 急速响应,体验省心
  • 根据需求灵活定制解决方案

基于netty的websocket开发小结

标签:基于netty的websocket开发小 2017-8-17 作者:open_tq54_niwe

  WebSocket是html5规范新引入的功能,用于解决浏览器与后台服务器双向通讯的问题,使用WebSocket技术,后台可以随时向前端推送消息,以保证前后台状态统一,在传统的无状态HTTP协议中,这是“无法做到”的。


  WebSocket提出之前,为了解决后台推送消息到前台的需求,提出了一些解决方案,这些方案使用已有的技术(如ajax,iframe,flashplayer,java applet ...),通过一些变通的处理来实现。


  webSocket是html5新引入的技术,允许后台随时向前端发送文本或者二进制消息,WebSocket是一种全新的协议,不属于http无状态协议,协议名为"ws",这意味着一个websocket连接地址会是这样的写法:


  ws://127.0.0.1:8080/websocket。ws不是http,所以传统的web服务器不一定支持,需要服务器与浏览器同时支持, WebSocket才能正常运行,目前的支持还不普遍,需要特别的web服务器和现代的浏览器。


  浏览器对WebSocket的支持


  Google Chrome浏览器最先支持WebSocket,随后是Safari,Firefox,此外最新版本的Opera和IE(Opera11,IE10)也支持WebSocket。


  客户端WebSocket的主要方法


  1 构造函数


  Java代码  收藏代码


  var websocket = new WebSocket("ws://127.0.0.1:8080/websocket");


  2 事件open/message/close/error


  WebSocket#onopen, onmessage, onclose, onerror


  连接打开时,回调onopen方法,接收到后台消息时会触发到onmessage事件,后台关闭时调用onclose,出现连接异常时可在onerror中捕获


  发送消息 - WebSocket#send(data)


  关闭连接 - WebSocket#close(optional code, optional reason)


  下面是一个简单的html5连接websocket服务器测试页


  Html代码  收藏代码


  


  


  


  


  


  


  


  


  


  


  


  


  服务器对WebSocket的支持


  WebSocket不同于http协议,传统的web服务器通常不支持WebSocket.而websocket服务器端的开发大概有借助Socket.IO开发、NodeJS和Socket.IO联合开发以及借助netty框架开发等等。这里只对netty框架下的websocket开发进行一个简单的说明!


  websocket的协议比较简单, 客户端和普通的浏览器一样通过80或者443端口和服务器进行请求握手,服务器根据http header识别是否一个websocket请求,如果是,则将请求升级为一个websocket连接,握手成功后就进入双向长连接的数据传输阶段. websocket的数据传输是基于帧的方式: 0x00 表示数据开始, 0xff表示数据结束,数据以utf-8编码.


  简单的说,第一次请求客户端发送的是http请求,请求头中包含websocket相关的信息,服务器端对请求进行验证:


  Java代码  收藏代码


  private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req) throws Exception {


  // Allow only GET methods.


  if (req.getMethod() != GET) {


  sendHttpResponse(ctx, req, new DefaultHttpResponse(HTTP_1_1, FORBIDDEN));


  return;


  }


  // Send the demo page and favicon.ico


  if (req.getUri().equals("/")) {


  HttpResponse res = new DefaultHttpResponse(HTTP_1_1, OK);


  ChannelBuffer content = WebSocketServerIndexPage.getContent(getWebSocketLocation(req));


  res.setHeader(CONTENT_TYPE, "text/html; charset=UTF-8");


  setContentLength(res, content.readableBytes());


  res.setContent(content);


  sendHttpResponse(ctx, req, res);


  return;


  } else if (req.getUri().equals("/favicon.ico")) {


  HttpResponse res = new DefaultHttpResponse(HTTP_1_1, NOT_FOUND);


  sendHttpResponse(ctx, req, res);


  return;


  }


  // Handshake


  WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(


  this.getWebSocketLocation(req), null, false);


  this.handshaker = wsFactory.newHandshaker(req);


  if (this.handshaker == null) {


  wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.getChannel());


  } else {


  this.handshaker.handshake(ctx.getChannel(), req);


  System.out.println(WebSocketServer.recipients.size());


  WebSocketServer.recipients.add(ctx.getChannel());


  System.out.println(WebSocketServer.recipients.size());


  System.out.println(ctx.getChannel().getId());


  }


  }


  验证成功后,将请求升级为一个websocket连接,之后的通信就进入双向长连接的数据传输阶段。


  Java代码  收藏代码


  private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {


  // Check for closing frame


  if (frame instanceof CloseWebSocketFrame) {


  this.handshaker.close(ctx.getChannel(), (CloseWebSocketFrame) frame);


  return;


  } else if (frame instanceof PingWebSocketFrame) {


  ctx.getChannel().write(new PongWebSocketFrame(frame.getBinaryData()));


  return;


  } else if (!(frame instanceof TextWebSocketFrame)) {


  throw new UnsupportedOperationException(String.format("%s frame types not supported", frame.getClass()


  .getName()));


  }


  // Send the uppercase string back.


  String request = ((TextWebSocketFrame) frame).getText();


  logger.debug(String.format("Channel %s received %s", ctx.getChannel().getId(), request));


  WebSocketServer.recipients.write(new TextWebSocketFrame(request.toUpperCase()));


  ctx.getChannel().write(new TextWebSocketFrame(request.toUpperCase()));


  }


  一定要注意在messageReceived中要对HttpRequest和WebSocketFrame分别进行处理。


  Java代码  收藏代码


  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {


  Object msg = e.getMessage();


  if (msg instanceof HttpRequest) {


  handleHttpRequest(ctx, (HttpRequest) msg);


  } else if (msg instanceof WebSocketFrame) {


  handleWebSocketFrame(ctx, (WebSocketFrame) msg);


  }


  }


  服务入口


  Java代码  收藏代码


  package com.etao.mobile.websocket;


  import java.net.InetSocketAddress;


  import java.util.concurrent.Executors;


  import org.jboss.netty.bootstrap.ServerBootstrap;


  import org.jboss.netty.channel.group.ChannelGroup;


  import org.jboss.netty.channel.group.DefaultChannelGroup;


  import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;


  /**


  * A HTTP server which serves Web Socket requests at:


  *


  * //localhost:8080/websocket


  *


  * Open your browser at //localhost:8080/, then the demo page will be


  * loaded and a Web Socket connection will be made automatically.


  *


  * This server illustrates support for the different web socket specification


  * versions and will work with:


  *


  *


      *

  • Safari 5+ (draft-ietf-hybi-thewebsocketprotocol-00)


      *

  • Chrome 6-13 (draft-ietf-hybi-thewebsocketprotocol-00)


      *

  • Chrome 14+ (draft-ietf-hybi-thewebsocketprotocol-10)


      *

  • Chrome 16+ (RFC 6455 aka draft-ietf-hybi-thewebsocketprotocol-17)


      *

  • Firefox 7+ (draft-ietf-hybi-thewebsocketprotocol-10)


      *


  */


  public class WebSocketServer {


  private final int port;


  public static ChannelGroup recipients = new DefaultChannelGroup();


  public WebSocketServer(int port) {


  this.port = port;


  }


  public void run() {


  // Configure the server.


  ServerBootstrap bootstrap = new ServerBootstrap(


  new NioServerSocketChannelFactory(Executors


  .newCachedThreadPool(), Executors.newCachedThreadPool()));


  // Set up the event pipeline factory.


  bootstrap.setPipelineFactory(new WebSocketServerPipelineFactory());


  // Bind and start to accept incoming connections.


  bootstrap.bind(new InetSocketAddress(port));


  System.out.println("Web socket server started at port " + port + '.');


  System.out


  .println("Open your browser and navigate to //localhost:"


  + port + '/');


  }


  public static void main(String[] args) {


  int port;


  if (args.length > 0) {


  port = Integer.parseInt(args[0]);


  } else {


  port = 8080;


  }


  new WebSocketServer(port).run();


  }


  }


  一定要注意的是netty3.0一下的版本是不支持websocket的!我这里用的是3.3.0.Final版本。


  可能存在的隐患:不同草案的websocket 握手标准有所不同,因此netty在这方面的检测是否可以满足要求?


  上面就是小编为大家整理的关于基于netty的websocket开发小结的文章,希望对大家有帮助。在实际的操作过程中大家可以根据实际情况进行灵活的调整。了解更多咨询请关注猪八戒网。


最新文章推荐

软件开发暂无最新文章查看全部推荐文章>

推荐人才