当前位置:   article > 正文

搭建WebSocket服务器与客户端_websocketserverprotocolhandler 客户端示例

websocketserverprotocolhandler 客户端示例

市场上有几款比较好的开源库供使用,比如PyWebSocket,WebSocket-Node, LibWebSockets等,这些库文件已经实现了WebSocket数据包的封装和解析,我们可以调用这些接口减少工作量。

1.     PyWebSocket

PyWebSocket采用Python语言编写,可以很好的跨平台,扩展起来也比较简单,目前WebKit采用它搭建WebSocket服务器来做LayoutTest,参见http://code.google.com/p/pywebsocket/

2.WebSocket-Node

WebSocket-Node采用JavaScript语言编写,这个库是建立在nodejs之上的,参见https://github.com/Worlize/Websocket-Node

3. LibWebSockets

LibWebSockets采用C/C++语言编写,可定制化的力度更大,从TCP监听开始到封包的完成我们都可以参与编程。参见git://git.warmcat.com/libwebsockets

4.Netty

采用了 Netty 中的 NIO 来构建 WebSocket 后端,参见:https://github.com/netty/netty

一.下面介绍一下用Netty搭建WebSocket服务器

1.WebsocketChatServer .java

  1. package com.waylau.netty.demo.websocketchat;
  2. import io.netty.bootstrap.ServerBootstrap;
  3. import io.netty.channel.ChannelFuture;
  4. import io.netty.channel.ChannelOption;
  5. import io.netty.channel.EventLoopGroup;
  6. import io.netty.channel.nio.NioEventLoopGroup;
  7. import io.netty.channel.socket.nio.NioServerSocketChannel;
  8. /**
  9. * Websocket 聊天服务器-服务端
  10. *
  11. * @author waylau.com
  12. * @date 2015-3-7
  13. */
  14. public class WebsocketChatServer {
  15. private int port;
  16. public WebsocketChatServer(int port) {
  17. this.port = port;
  18. }
  19. public void run() throws Exception {
  20. EventLoopGroup bossGroup = new NioEventLoopGroup();
  21. EventLoopGroup workerGroup = new NioEventLoopGroup();
  22. try {
  23. ServerBootstrap b = new ServerBootstrap();
  24. b.group(bossGroup, workerGroup)
  25. .channel(NioServerSocketChannel.class) // (3)
  26. .childHandler(new WebsocketChatServerInitializer()) //处理初始化类
  27. .option(ChannelOption.SO_BACKLOG, 128)
  28. .childOption(ChannelOption.SO_KEEPALIVE, true); // 保持长连接
  29. System.out.println("WebsocketChatServer 启动了" + port);
  30. // 绑定端口,开始接收进来的连接
  31. ChannelFuture f = b.bind(port).sync(); // (7)
  32. // 等待服务器 socket 关闭 。
  33. // 在这个例子中,这不会发生,但你可以优雅地关闭你的服务器。
  34. f.channel().closeFuture().sync();
  35. } finally {
  36. workerGroup.shutdownGracefully();
  37. bossGroup.shutdownGracefully();
  38. System.out.println("WebsocketChatServer 关闭了");
  39. }
  40. }
  41. public static void main(String[] args) throws Exception {
  42. int port;
  43. if (args.length > 0) {
  44. port = Integer.parseInt(args[0]);
  45. } else {
  46. port = 8080;
  47. }
  48. new WebsocketChatServer(port).run();
  49. }
  50. }
2.服务端 ChannelInitializer

  1. package com.waylau.netty.demo.websocketchat;
  2. import io.netty.channel.ChannelInitializer;
  3. import io.netty.channel.ChannelPipeline;
  4. import io.netty.channel.socket.SocketChannel;
  5. import io.netty.handler.codec.http.HttpObjectAggregator;
  6. import io.netty.handler.codec.http.HttpServerCodec;
  7. import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
  8. import io.netty.handler.stream.ChunkedWriteHandler;
  9. /**
  10. * 服务端 ChannelInitializer
  11. *
  12. * @author
  13. * @date 2015-3-13
  14. */
  15. public class WebsocketChatServerInitializer extends
  16. ChannelInitializer<SocketChannel> { //1
  17. @Override
  18. public void initChannel(SocketChannel ch) throws Exception {//2
  19. ChannelPipeline pipeline = ch.pipeline();
  20. pipeline.addLast(new HttpServerCodec());
  21. pipeline.addLast(new HttpObjectAggregator(64*1024));
  22. pipeline.addLast(new ChunkedWriteHandler());
  23. pipeline.addLast(new HttpRequestHandler("/ws"));
  24. pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
  25. pipeline.addLast(new TextWebSocketFrameHandler());
  26. }
  27. }
3.处理TextWebSocketFrame

  1. package com.waylau.netty.demo.websocketchat;
  2. import io.netty.channel.Channel;
  3. import io.netty.channel.ChannelHandlerContext;
  4. import io.netty.channel.SimpleChannelInboundHandler;
  5. import io.netty.channel.group.ChannelGroup;
  6. import io.netty.channel.group.DefaultChannelGroup;
  7. import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
  8. import io.netty.util.concurrent.GlobalEventExecutor;
  9. /**
  10. * 处理TextWebSocketFrame
  11. *
  12. * @author
  13. * 2015年3月26日
  14. */
  15. public class TextWebSocketFrameHandler extends
  16. SimpleChannelInboundHandler<TextWebSocketFrame> {
  17. public static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
  18. @Override
  19. protected void channelRead0(ChannelHandlerContext ctx,
  20. TextWebSocketFrame msg) throws Exception { // 读取数据并转发
  21. Channel incoming = ctx.channel();
  22. for (Channel channel : channels) {
  23. if (channel != incoming){
  24. channel.writeAndFlush(new TextWebSocketFrame(msg.text()));
  25. } else {
  26. channel.writeAndFlush(new TextWebSocketFrame(msg.text()));
  27. }
  28. }
  29. }
  30. @Override
  31. public void handlerAdded(ChannelHandlerContext ctx) throws Exception { // 连接时调用
  32. Channel incoming = ctx.channel();
  33. // Broadcast a message to multiple Channels
  34. channels.writeAndFlush(new TextWebSocketFrame("[SERVER] - " + incoming.remoteAddress() + " 加入"));
  35. channels.add(incoming);
  36. System.out.println("Client:"+incoming.remoteAddress() +"加入");
  37. }
  38. @Override
  39. public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { // 移除时调用
  40. Channel incoming = ctx.channel();
  41. // Broadcast a message to multiple Channels
  42. channels.writeAndFlush(new TextWebSocketFrame("[SERVER] - " + incoming.remoteAddress() + " 离开"));
  43. System.out.println("Client:"+incoming.remoteAddress() +"离开");
  44. // A closed Channel is automatically removed from ChannelGroup,
  45. // so there is no need to do "channels.remove(ctx.channel());"
  46. }
  47. @Override
  48. public void channelActive(ChannelHandlerContext ctx) throws Exception { //
  49. Channel incoming = ctx.channel();
  50. System.out.println("Client:"+incoming.remoteAddress()+"在线");
  51. }
  52. @Override
  53. public void channelInactive(ChannelHandlerContext ctx) throws Exception { //
  54. Channel incoming = ctx.channel();
  55. System.out.println("Client:"+incoming.remoteAddress()+"掉线");
  56. }
  57. @Override
  58. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) // 异常则关闭
  59. throws Exception {
  60. Channel incoming = ctx.channel();
  61. System.out.println("Client:"+incoming.remoteAddress()+"异常");
  62. // 当出现异常就关闭连接
  63. cause.printStackTrace();
  64. ctx.close();
  65. }
  66. }
二.,客户端

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>WebSocket Chat</title>
  6. </head>
  7. <body>
  8. <script type="text/javascript">
  9. var socket;
  10. if (!window.WebSocket) {
  11. window.WebSocket = window.MozWebSocket;
  12. }
  13. if (window.WebSocket) {
  14. socket = new WebSocket("ws://192.169.1.101:8080/ws");
  15. socket.onmessage = function(event) {
  16. var ta = document.getElementById('responseText');
  17. ta.value = ta.value + '\n' + event.data
  18. };
  19. socket.onopen = function(event) {
  20. var ta = document.getElementById('responseText');
  21. ta.value = "连接开启!";
  22. };
  23. socket.onclose = function(event) {
  24. var ta = document.getElementById('responseText');
  25. ta.value = ta.value + "连接被关闭";
  26. };
  27. } else {
  28. alert("你的浏览器不支持 WebSocket!");
  29. }
  30. function send(message) {
  31. if (!window.WebSocket) {
  32. return;
  33. }
  34. if (socket.readyState == WebSocket.OPEN) {
  35. socket.send(message);
  36. } else {
  37. alert("连接没有开启.");
  38. }
  39. }
  40. </script>
  41. <form οnsubmit="return false;">
  42. <h3>WebSocket 聊天室:</h3>
  43. <textarea id="responseText" style="width: 500px; height: 300px;"></textarea>
  44. <br>
  45. <input type="text" name="message" style="width: 300px" value="Welcome to www.waylau.com">
  46. <input type="button" value="发送消息" οnclick="send(this.form.message.value)">
  47. <input type="button" οnclick="javascript:document.getElementById('responseText').value=''" value="清空聊天记录">
  48. </form>
  49. <br>
  50. <br>
  51. </body>
  52. </html>
点击下载源码




声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/634578
推荐阅读
相关标签
  

闽ICP备14008679号