基于Netty最简单的WebSocket通讯

  • 基于Netty最简单的WebSocket通讯

    • 总览
    • 服务端
      • EasyWsServer
      • EasyWsServerHandler
    • 客户端
      • EasyWsClient
      • EasyWsClientHandler
    • 测试类
      • EasyWsTest
    • 测试

总览

  1. 总共是五个文件:

    • client

      • EasyWsClient 客户端
      • EasyWsClientHandler 客户端消息处理类
    • server
      • EasyWsServer 服务端
      • EasyWsServerHandler 服务端消息处理类
    • EasyWsTest 测试类
  2. EasyWsServer启动时需要声明一个ServerBootstrap,ServerBootstrap里面初始化需要添加一个handler。
  3. WebSocket通讯和普通的tcp通讯不同的是,他有2个格式的消息需要处理
    • 流程:

      • http请求握手
      • 握手完成后的长连接通讯
    • 消息
      • http消息,如:FullHttpRequest、FullHttpResponse等
      • websocket消息,如TextWebSocketFrame(文本类消息),BinaryWebSocketFrame(字节类数据)等
  4. 客户端第一次发送http握手请求的时候,需要使用WebSocketClientHandshaker
  5. 里面处理了文本消息,二进制字节消息。

服务端

EasyWsServer

/** Copyright (C), 2015-2018* FileName: EasyWsServer* Author:   zhao* Date:     2018/8/14 10:43* Description: 简单的WebScoket服务器* History:* <author>          <time>          <version>          <desc>* 作者姓名           修改时间           版本号              描述*/
package com.lizhaoblog.demopro.websocket.server;import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.stream.ChunkedWriteHandler;/*** 〈一句话功能简述〉<br>* 〈简单的WebScoket服务器〉** @author zhao* @date 2018/8/14 10:43* @since 1.0.1*/
public class EasyWsServer {private int port;public EasyWsServer(int port) {this.port = port;}public void start() throws InterruptedException {ServerBootstrap serverBootstrap = new ServerBootstrap();EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();serverBootstrap.group(bossGroup, workerGroup);serverBootstrap.channel(NioServerSocketChannel.class);serverBootstrap.childHandler(new ChannelInitializer() {@Overrideprotected void initChannel(Channel channel) throws Exception {ChannelPipeline pipeline = channel.pipeline();pipeline.addLast("http-codec", new HttpServerCodec()); // Http消息编码解码pipeline.addLast("aggregator", new HttpObjectAggregator(65536)); // Http消息组装pipeline.addLast("http-chunked", new ChunkedWriteHandler()); // WebSocket通信支持pipeline.addLast(new EasyWsServerHandler());}});// 监听端口ChannelFuture channelFuture = serverBootstrap.bind(port).sync();channelFuture.awaitUninterruptibly();// 堵塞线程,保持长连接channelFuture.channel().closeFuture().sync();}}

EasyWsServerHandler

/** Copyright (C), 2015-2018* FileName: EasyWsServerHandler* Author:   zhao* Date:     2018/8/14 10:44* Description: 简单的WebSocket服务器* History:* <author>          <time>          <version>          <desc>* 作者姓名           修改时间           版本号              描述*/
package com.lizhaoblog.demopro.websocket.server;import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpUtil;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory;
import io.netty.util.CharsetUtil;/*** 〈一句话功能简述〉<br>* 〈简单的WebSocket服务器〉** @author zhao* @date 2018/8/14 10:44* @since 1.0.1*/
public class EasyWsServerHandler extends SimpleChannelInboundHandler<Object> {@Overrideprotected void channelRead0(ChannelHandlerContext channelHandlerContext, Object msg) throws Exception {if (msg instanceof FullHttpRequest) {// 传统的HTTP接入handleHttpMessage(channelHandlerContext, msg);} else if (msg instanceof WebSocketFrame) {// WebSocket接入handleWebSocketMessage(channelHandlerContext, msg);}}/*** 处理WebSocket中的Http消息** @param ctx 上下文* @param msg 消息*/private void handleHttpMessage(ChannelHandlerContext ctx, Object msg) {// 传统的HTTP接入FullHttpRequest request = (FullHttpRequest) msg;// 如果HTTP解码失败,返回HHTP异常if (!request.decoderResult().isSuccess() || (!"websocket".equals(request.headers().get("Upgrade")))) {sendHttpResponse(ctx, request, new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST));return;}// 正常WebSocket的Http连接请求,构造握手响应返回WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory("ws://" + request.headers().get(HttpHeaderNames.HOST), null, false);WebSocketServerHandshaker handshaker = wsFactory.newHandshaker(request);if (handshaker == null) { // 无法处理的websocket版本WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());} else { // 向客户端发送websocket握手,完成握手handshaker.handshake(ctx.channel(), request);}}/*** Http返回** @param ctx* @param request* @param response*/public static void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest request, FullHttpResponse response) {// 返回应答给客户端if (response.status().code() != 200) {ByteBuf buf = Unpooled.copiedBuffer(response.status().toString(), CharsetUtil.UTF_8);response.content().writeBytes(buf);buf.release();HttpUtil.setContentLength(response, response.content().readableBytes());}// 如果是非Keep-Alive,关闭连接ChannelFuture f = ctx.channel().writeAndFlush(response);if (!HttpUtil.isKeepAlive(request) || response.status().code() != 200) {f.addListener(ChannelFutureListener.CLOSE);}}/*** 处理WebSocket中的WebSocket消息** @param ctx 上下文* @param msg 消息*/private void handleWebSocketMessage(ChannelHandlerContext ctx, Object msg) {//    ByteBuf content = ((WebSocketFrame) msg).content();WebSocketFrame frame = (WebSocketFrame) msg;if (frame instanceof TextWebSocketFrame) {TextWebSocketFrame textFrame = (TextWebSocketFrame) frame;System.out.println("服务器:接收到你的TextWebSocketFrame消息,内容是 " + textFrame.text());// 返回消息给客户端ctx.writeAndFlush(new TextWebSocketFrame("我是服务器,我是服务器"));} else if (frame instanceof BinaryWebSocketFrame) {System.out.println("服务器:接收到你的BinaryWebSocketFrame消息,内容是 ");ByteBuf content = frame.content();byte[] result = new byte[content.readableBytes()];content.readBytes(result);for (byte b : result) {System.out.print(b);System.out.print(",");}System.out.println();ctx.writeAndFlush(new BinaryWebSocketFrame(Unpooled.copiedBuffer(result)));}}@Overridepublic void channelActive(ChannelHandlerContext ctx) {System.out.println("服务器:连接建立");}@Overridepublic void channelInactive(ChannelHandlerContext ctx) {System.out.println("服务器:断开连接");}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable) {System.out.println("服务器:异常发送");throwable.printStackTrace();}}

客户端

EasyWsClient

/** Copyright (C), 2015-2018* FileName: EasyWsClient* Author:   zhao* Date:     2018/8/14 10:23* Description: 最简单的websocket客户端* History:* <author>          <time>          <version>          <desc>* 作者姓名           修改时间           版本号              描述*/
package com.lizhaoblog.demopro.websocket.client;import java.net.URI;
import java.net.URISyntaxException;import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
import io.netty.handler.codec.http.websocketx.WebSocketVersion;/*** 〈一句话功能简述〉<br>* 〈最简单的websocket客户端〉** @author zhao* @date 2018/8/14 10:23* @since 1.0.1*/
public class EasyWsClient {private static EventLoopGroup group = new NioEventLoopGroup();//  private static final String ip = "127.0.0.1";//  private static final int port = 8088;private String ip;private int port;private String uriStr;private static EasyWsClientHandler handler;public EasyWsClient(String ip, int port) {this.ip = ip;this.port = port;uriStr = "ws//" + ip + ":" + port;}public void run() throws InterruptedException, URISyntaxException {// 主要是为handler(自己写的类)服务,用于初始化EasyWsHandleURI wsUri = new URI(uriStr);WebSocketClientHandshaker webSocketClientHandshaker = WebSocketClientHandshakerFactory.newHandshaker(wsUri, WebSocketVersion.V13, null, true, new DefaultHttpHeaders(), 100 * 1024 * 1024);handler = new EasyWsClientHandler(webSocketClientHandshaker);// 设置BootstrapBootstrap bootstrap = new Bootstrap();bootstrap.group(group);bootstrap.channel(NioSocketChannel.class);bootstrap.handler(new ChannelInitializer() {@Overrideprotected void initChannel(Channel ch) {ChannelPipeline pipeline = ch.pipeline();pipeline.addLast(new HttpClientCodec());pipeline.addLast(new HttpObjectAggregator(65536));pipeline.addLast(handler);}});// 连接服务端ChannelFuture channelFuture = bootstrap.connect(ip, port).sync();handler.handshakeFuture().sync();// 传输文本TextWebSocketFrame frame = new TextWebSocketFrame("hello");channelFuture.channel().writeAndFlush(frame);// 传输二进制字节数据byte[] bytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };BinaryWebSocketFrame byteFrame = new BinaryWebSocketFrame(Unpooled.copiedBuffer(bytes));channelFuture.channel().writeAndFlush(byteFrame);// 堵塞线程,保持长连接channelFuture.channel().closeFuture().sync();}}

EasyWsClientHandler

/** Copyright (C), 2015-2018* FileName: EasyWsClientHandler* Author:   zhao* Date:     2018/8/14 10:23* Description: 最简单的WebSocket的handle* History:* <author>          <time>          <version>          <desc>* 作者姓名           修改时间           版本号              描述*/
package com.lizhaoblog.demopro.websocket.client;import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.util.CharsetUtil;/*** 〈一句话功能简述〉<br>* 〈最简单的WebSocket的handle〉** @author zhao* @date 2018/8/14 10:23* @since 1.0.1*/
public class EasyWsClientHandler extends SimpleChannelInboundHandler<Object> {private final WebSocketClientHandshaker handshaker;private ChannelPromise handshakeFuture;public EasyWsClientHandler(WebSocketClientHandshaker handshaker) {this.handshaker = handshaker;}public ChannelFuture handshakeFuture() {return handshakeFuture;}@Overridepublic void handlerAdded(ChannelHandlerContext ctx) {handshakeFuture = ctx.newPromise();}@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {System.out.println("客户端连接建立");// 在通道连接成功后发送握手连接handshaker.handshake(ctx.channel());super.channelActive(ctx);}@Overrideprotected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {Channel ch = ctx.channel();// 这里是第一次使用http连接成功的时候if (!handshaker.isHandshakeComplete()) {handshaker.finishHandshake(ch, (FullHttpResponse) msg);System.out.println("WebSocket Client connected!");handshakeFuture.setSuccess();return;}// 这里是第一次使用http连接失败的时候if (msg instanceof FullHttpResponse) {FullHttpResponse response = (FullHttpResponse) msg;throw new IllegalStateException("Unexpected FullHttpResponse (getStatus=" + response.getStatus() + ", content=" + response.content().toString(CharsetUtil.UTF_8) + ')');}// 这里是服务器与客户端进行通讯的WebSocketFrame frame = (WebSocketFrame) msg;if (frame instanceof TextWebSocketFrame) {TextWebSocketFrame textFrame = (TextWebSocketFrame) frame;System.out.println("客户端:接收到TextWebSocketFrame消息,消息内容是-- " + textFrame.text());} else if (frame instanceof BinaryWebSocketFrame) {System.out.println("客户端:接收到BinaryWebSocketFrame消息,消息内容是-- ");ByteBuf content = frame.content();byte[] result = new byte[content.readableBytes()];content.readBytes(result);for (byte b : result) {System.out.print(b);System.out.print(",");}System.out.println();} else if (frame instanceof PongWebSocketFrame) {System.out.println("WebSocket Client received pong");} else if (frame instanceof CloseWebSocketFrame) {System.out.println("WebSocket Client received closing");ch.close();}}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable arg1) {System.out.println("异常发生");arg1.printStackTrace();}@Overridepublic void channelInactive(ChannelHandlerContext ctx) throws Exception {System.out.println("客户端连接断开");super.channelInactive(ctx);}
}

测试类

EasyWsTest

/** Copyright (C), 2015-2018* FileName: EasyWsTest* Author:   zhao* Date:     2018/8/14 11:08* Description: EasyWs的测试类* History:* <author>          <time>          <version>          <desc>* 作者姓名           修改时间           版本号              描述*/
package com.lizhaoblog.demopro.websocket;import com.lizhaoblog.demopro.websocket.client.EasyWsClient;
import com.lizhaoblog.demopro.websocket.server.EasyWsServer;import org.junit.Test;/*** 〈一句话功能简述〉<br>* 〈EasyWs的测试类〉** @author zhao* @date 2018/8/14 11:08* @since 1.0.1*/
public class EasyWsTest {private static final String IP = "127.0.0.1";private static final int PORT = 8088;@Testpublic void startServer() throws Exception {EasyWsServer easyWsServer = new EasyWsServer(PORT);easyWsServer.start();}@Testpublic void startClient() throws Exception {EasyWsClient easyWsClient = new EasyWsClient(IP, PORT);easyWsClient.run();}
}

测试

  1. 打开EasyWsTest,运行startServer
  2. 打开EasyWsTest,运行startClient
  3. 查看结果
    • 服务端:连接建立–服务器收到http握手消息–服务器收到消息(文本)–服务器收到字节消息
    • 服务端
Connected to the target VM, address: '127.0.0.1:3215', transport: 'socket'
2018-08-14 11:55:39.087 DEBUG io.netty.util.internal.logging.InternalLoggerFactory - Using SLF4J as the default logging framework
2018-08-14 11:55:39.099 DEBUG io.netty.channel.MultithreadEventLoopGroup - -Dio.netty.eventLoopThreads: 16
2018-08-14 11:55:39.122 DEBUG io.netty.util.internal.PlatformDependent0 - java.nio.Buffer.address: available
2018-08-14 11:55:39.123 DEBUG io.netty.util.internal.PlatformDependent0 - sun.misc.Unsafe.theUnsafe: available
2018-08-14 11:55:39.123 DEBUG io.netty.util.internal.PlatformDependent0 - sun.misc.Unsafe.copyMemory: available
2018-08-14 11:55:39.124 DEBUG io.netty.util.internal.PlatformDependent0 - direct buffer constructor: available
2018-08-14 11:55:39.125 DEBUG io.netty.util.internal.PlatformDependent0 - java.nio.Bits.unaligned: available, true
2018-08-14 11:55:39.125 DEBUG io.netty.util.internal.PlatformDependent0 - java.nio.DirectByteBuffer.<init>(long, int): available
2018-08-14 11:55:39.126 DEBUG io.netty.util.internal.Cleaner0 - java.nio.ByteBuffer.cleaner(): available
2018-08-14 11:55:39.126 DEBUG io.netty.util.internal.PlatformDependent - Platform: Windows
2018-08-14 11:55:39.127 DEBUG io.netty.util.internal.PlatformDependent - Java version: 8
2018-08-14 11:55:39.127 DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.noUnsafe: false
2018-08-14 11:55:39.127 DEBUG io.netty.util.internal.PlatformDependent - sun.misc.Unsafe: available
2018-08-14 11:55:39.127 DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.noJavassist: false
2018-08-14 11:55:39.128 DEBUG io.netty.util.internal.PlatformDependent - Javassist: unavailable
2018-08-14 11:55:39.128 DEBUG io.netty.util.internal.PlatformDependent - You don't have Javassist in your class path or you don't have enough permission to load dynamically generated classes.  Please check the configuration for better performance.
2018-08-14 11:55:39.129 DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.tmpdir: C:\Users\ADMINI~1\AppData\Local\Temp (java.io.tmpdir)
2018-08-14 11:55:39.129 DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.bitMode: 64 (sun.arch.data.model)
2018-08-14 11:55:39.129 DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.noPreferDirect: false
2018-08-14 11:55:39.129 DEBUG io.netty.util.internal.PlatformDependent - io.netty.maxDirectMemory: 3806855168 bytes
2018-08-14 11:55:39.183 DEBUG io.netty.channel.nio.NioEventLoop - -Dio.netty.noKeySetOptimization: false
2018-08-14 11:55:39.184 DEBUG io.netty.channel.nio.NioEventLoop - -Dio.netty.selectorAutoRebuildThreshold: 512
2018-08-14 11:55:39.186 DEBUG io.netty.util.internal.PlatformDependent - org.jctools-core.MpscChunkedArrayQueue: available
2018-08-14 11:55:39.380 DEBUG io.netty.channel.DefaultChannelId - -Dio.netty.processId: 6492 (auto-detected)
2018-08-14 11:55:39.382 DEBUG io.netty.util.NetUtil - -Djava.net.preferIPv4Stack: false
2018-08-14 11:55:39.383 DEBUG io.netty.util.NetUtil - -Djava.net.preferIPv6Addresses: false
2018-08-14 11:55:39.411 DEBUG io.netty.util.NetUtil - Loopback interface: lo (Software Loopback Interface 1, 127.0.0.1)
2018-08-14 11:55:39.412 DEBUG io.netty.util.NetUtil - \proc\sys\net\core\somaxconn: 200 (non-existent)
2018-08-14 11:55:39.444 DEBUG io.netty.channel.DefaultChannelId - -Dio.netty.machineId: 94:de:80:ff:fe:78:f9:54 (auto-detected)
2018-08-14 11:55:39.447 DEBUG io.netty.util.internal.ThreadLocalRandom - -Dio.netty.initialSeedUniquifier: 0x912cf1a5dfc99b85
2018-08-14 11:55:39.466 DEBUG io.netty.util.ResourceLeakDetector - -Dio.netty.leakDetection.level: simple
2018-08-14 11:55:39.467 DEBUG io.netty.util.ResourceLeakDetector - -Dio.netty.leakDetection.maxRecords: 4
2018-08-14 11:55:39.497 DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.numHeapArenas: 16
2018-08-14 11:55:39.497 DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.numDirectArenas: 16
2018-08-14 11:55:39.498 DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.pageSize: 8192
2018-08-14 11:55:39.498 DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.maxOrder: 11
2018-08-14 11:55:39.498 DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.chunkSize: 16777216
2018-08-14 11:55:39.498 DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.tinyCacheSize: 512
2018-08-14 11:55:39.498 DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.smallCacheSize: 256
2018-08-14 11:55:39.498 DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.normalCacheSize: 64
2018-08-14 11:55:39.498 DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.maxCachedBufferCapacity: 32768
2018-08-14 11:55:39.498 DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.cacheTrimInterval: 8192
2018-08-14 11:55:39.512 DEBUG io.netty.buffer.ByteBufUtil - -Dio.netty.allocator.type: pooled
2018-08-14 11:55:39.513 DEBUG io.netty.buffer.ByteBufUtil - -Dio.netty.threadLocalDirectBufferSize: 65536
2018-08-14 11:55:39.513 DEBUG io.netty.buffer.ByteBufUtil - -Dio.netty.maxThreadLocalCharBufferSize: 16384
2018-08-14 11:55:42.719 DEBUG io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.bytebuf.checkAccessible: true
2018-08-14 11:55:42.724 DEBUG io.netty.util.ResourceLeakDetectorFactory - Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@42e2b085
服务器:连接建立
2018-08-14 11:55:42.788 DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxCapacityPerThread: 32768
2018-08-14 11:55:42.788 DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxSharedCapacityFactor: 2
2018-08-14 11:55:42.788 DEBUG io.netty.util.Recycler - -Dio.netty.recycler.linkCapacity: 16
2018-08-14 11:55:42.788 DEBUG io.netty.util.Recycler - -Dio.netty.recycler.ratio: 8
2018-08-14 11:55:42.836 DEBUG io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker - [id: 0x08778b2d, L:/127.0.0.1:8088 - R:/127.0.0.1:3327] WebSocket version V13 server handshake
2018-08-14 11:55:42.842 DEBUG io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker - WebSocket version 13 server handshake key: YR/wvrnrJz9kEkn6LSuFug==, response: 6XulC19MJ2P54cdvYMhyy/OHqNU=
2018-08-14 11:55:42.871 DEBUG io.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder - Decoding WebSocket Frame opCode=1
2018-08-14 11:55:42.871 DEBUG io.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder - Decoding WebSocket Frame length=5
服务器:接收到你的TextWebSocketFrame消息,内容是 hello
2018-08-14 11:55:42.873 DEBUG io.netty.handler.codec.http.websocketx.WebSocket08FrameEncoder - Encoding WebSocket Frame opCode=1 length=33
2018-08-14 11:55:42.874 DEBUG io.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder - Decoding WebSocket Frame opCode=2
2018-08-14 11:55:42.874 DEBUG io.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder - Decoding WebSocket Frame length=9
服务器:接收到你的BinaryWebSocketFrame消息,内容是
1,2,3,4,5,6,7,8,9,
2018-08-14 11:55:42.879 DEBUG io.netty.handler.codec.http.websocketx.WebSocket08FrameEncoder - Encoding WebSocket Frame opCode=2 length=9
Disconnected from the target VM, address: '127.0.0.1:3215', transport: 'socket'Process finished with exit code -1
- 客户端
2018-08-14 11:55:42.240 DEBUG io.netty.util.internal.logging.InternalLoggerFactory - Using SLF4J as the default logging framework
2018-08-14 11:55:42.246 DEBUG io.netty.channel.MultithreadEventLoopGroup - -Dio.netty.eventLoopThreads: 16
2018-08-14 11:55:42.271 DEBUG io.netty.util.internal.PlatformDependent0 - java.nio.Buffer.address: available
2018-08-14 11:55:42.272 DEBUG io.netty.util.internal.PlatformDependent0 - sun.misc.Unsafe.theUnsafe: available
2018-08-14 11:55:42.272 DEBUG io.netty.util.internal.PlatformDependent0 - sun.misc.Unsafe.copyMemory: available
2018-08-14 11:55:42.273 DEBUG io.netty.util.internal.PlatformDependent0 - direct buffer constructor: available
2018-08-14 11:55:42.274 DEBUG io.netty.util.internal.PlatformDependent0 - java.nio.Bits.unaligned: available, true
2018-08-14 11:55:42.274 DEBUG io.netty.util.internal.PlatformDependent0 - java.nio.DirectByteBuffer.<init>(long, int): available
2018-08-14 11:55:42.275 DEBUG io.netty.util.internal.Cleaner0 - java.nio.ByteBuffer.cleaner(): available
2018-08-14 11:55:42.276 DEBUG io.netty.util.internal.PlatformDependent - Platform: Windows
2018-08-14 11:55:42.277 DEBUG io.netty.util.internal.PlatformDependent - Java version: 8
2018-08-14 11:55:42.277 DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.noUnsafe: false
2018-08-14 11:55:42.277 DEBUG io.netty.util.internal.PlatformDependent - sun.misc.Unsafe: available
2018-08-14 11:55:42.277 DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.noJavassist: false
2018-08-14 11:55:42.278 DEBUG io.netty.util.internal.PlatformDependent - Javassist: unavailable
2018-08-14 11:55:42.279 DEBUG io.netty.util.internal.PlatformDependent - You don't have Javassist in your class path or you don't have enough permission to load dynamically generated classes.  Please check the configuration for better performance.
2018-08-14 11:55:42.279 DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.tmpdir: C:\Users\ADMINI~1\AppData\Local\Temp (java.io.tmpdir)
2018-08-14 11:55:42.279 DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.bitMode: 64 (sun.arch.data.model)
2018-08-14 11:55:42.282 DEBUG io.netty.util.internal.PlatformDependent - -Dio.netty.noPreferDirect: false
2018-08-14 11:55:42.282 DEBUG io.netty.util.internal.PlatformDependent - io.netty.maxDirectMemory: 3806855168 bytes
2018-08-14 11:55:42.301 DEBUG io.netty.channel.nio.NioEventLoop - -Dio.netty.noKeySetOptimization: false
2018-08-14 11:55:42.301 DEBUG io.netty.channel.nio.NioEventLoop - -Dio.netty.selectorAutoRebuildThreshold: 512
2018-08-14 11:55:42.303 DEBUG io.netty.util.internal.PlatformDependent - org.jctools-core.MpscChunkedArrayQueue: available
2018-08-14 11:55:42.488 DEBUG io.netty.channel.DefaultChannelId - -Dio.netty.processId: 18412 (auto-detected)
2018-08-14 11:55:42.490 DEBUG io.netty.util.NetUtil - -Djava.net.preferIPv4Stack: false
2018-08-14 11:55:42.491 DEBUG io.netty.util.NetUtil - -Djava.net.preferIPv6Addresses: false
2018-08-14 11:55:42.516 DEBUG io.netty.util.NetUtil - Loopback interface: lo (Software Loopback Interface 1, 127.0.0.1)
2018-08-14 11:55:42.518 DEBUG io.netty.util.NetUtil - \proc\sys\net\core\somaxconn: 200 (non-existent)
2018-08-14 11:55:42.545 DEBUG io.netty.channel.DefaultChannelId - -Dio.netty.machineId: 94:de:80:ff:fe:78:f9:54 (auto-detected)
2018-08-14 11:55:42.546 DEBUG io.netty.util.internal.ThreadLocalRandom - -Dio.netty.initialSeedUniquifier: 0x30542ca8d536a1bd
2018-08-14 11:55:42.561 DEBUG io.netty.util.ResourceLeakDetector - -Dio.netty.leakDetection.level: simple
2018-08-14 11:55:42.561 DEBUG io.netty.util.ResourceLeakDetector - -Dio.netty.leakDetection.maxRecords: 4
2018-08-14 11:55:42.590 DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.numHeapArenas: 16
2018-08-14 11:55:42.591 DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.numDirectArenas: 16
2018-08-14 11:55:42.591 DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.pageSize: 8192
2018-08-14 11:55:42.591 DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.maxOrder: 11
2018-08-14 11:55:42.591 DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.chunkSize: 16777216
2018-08-14 11:55:42.591 DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.tinyCacheSize: 512
2018-08-14 11:55:42.591 DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.smallCacheSize: 256
2018-08-14 11:55:42.592 DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.normalCacheSize: 64
2018-08-14 11:55:42.592 DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.maxCachedBufferCapacity: 32768
2018-08-14 11:55:42.592 DEBUG io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.cacheTrimInterval: 8192
2018-08-14 11:55:42.606 DEBUG io.netty.buffer.ByteBufUtil - -Dio.netty.allocator.type: pooled
2018-08-14 11:55:42.606 DEBUG io.netty.buffer.ByteBufUtil - -Dio.netty.threadLocalDirectBufferSize: 65536
2018-08-14 11:55:42.606 DEBUG io.netty.buffer.ByteBufUtil - -Dio.netty.maxThreadLocalCharBufferSize: 16384
2018-08-14 11:55:42.645 DEBUG io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.bytebuf.checkAccessible: true
2018-08-14 11:55:42.648 DEBUG io.netty.util.ResourceLeakDetectorFactory - Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@3724974
客户端连接建立
2018-08-14 11:55:42.681 DEBUG io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker13 - WebSocket version 13 client handshake key: YR/wvrnrJz9kEkn6LSuFug==, expected response: 6XulC19MJ2P54cdvYMhyy/OHqNU=
2018-08-14 11:55:42.690 DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxCapacityPerThread: 32768
2018-08-14 11:55:42.690 DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxSharedCapacityFactor: 2
2018-08-14 11:55:42.690 DEBUG io.netty.util.Recycler - -Dio.netty.recycler.linkCapacity: 16
2018-08-14 11:55:42.690 DEBUG io.netty.util.Recycler - -Dio.netty.recycler.ratio: 8
WebSocket Client connected!
2018-08-14 11:55:42.869 DEBUG io.netty.handler.codec.http.websocketx.WebSocket08FrameEncoder - Encoding WebSocket Frame opCode=1 length=5
2018-08-14 11:55:42.872 DEBUG io.netty.handler.codec.http.websocketx.WebSocket08FrameEncoder - Encoding WebSocket Frame opCode=2 length=9
2018-08-14 11:55:42.875 DEBUG io.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder - Decoding WebSocket Frame opCode=1
2018-08-14 11:55:42.875 DEBUG io.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder - Decoding WebSocket Frame length=33
客户端:接收到TextWebSocketFrame消息,消息内容是-- 我是服务器,我是服务器
2018-08-14 11:55:42.879 DEBUG io.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder - Decoding WebSocket Frame opCode=2
2018-08-14 11:55:42.880 DEBUG io.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder - Decoding WebSocket Frame length=9
客户端:接收到BinaryWebSocketFrame消息,消息内容是--
1,2,3,4,5,6,7,8,9,

上面的代码在码云上 https://gitee.com/lizhaoandroid/JgServer
的test下的com.lizhaoblog.demopro.websocket包目录下,可以下载查看

基于Netty最简单的WebSocket通讯相关推荐

  1. 基于Netty实现分布式IM即时通讯开发

    计算机编程的学习,能不能把知识学到手,讲究的是动手实践.在我编写的文章中,基本都是以实践代码验证结果为核心来讲述文章内容. 可能有人不知道 Netty 是什么,这里简单介绍下: Netty 是一个 J ...

  2. 基于netty的可群聊聊天室

    一.环境配置 <dependencies><dependency><groupId>io.netty</groupId><artifactId&g ...

  3. 基于netty实现一个简单的支持http和webSocket协议的的服务器(含xxl-job通信模块源码分析)

    文章目录 背景 依赖 包结构 实现 WebSocketServer 业务handler WebSocketServerHandler 测试 xxl-job 源码中基于netty实现的http 总结 参 ...

  4. 基于netty的websocket协议实现

    基于netty的websocket协议实现 背景 1.启动服务端 2.测试服务端和客户端效果 背景 项目中使用到了websocket,所以查阅相关资料,完成了一个基于netty的websocket的实 ...

  5. 一款基于Netty开发的WebSocket服务器

    代码地址如下: http://www.demodashi.com/demo/13577.html 一款基于Netty开发的WebSocket服务器 这是一款基于Netty框架开发的服务端,通信协议为W ...

  6. 基于netty+websocket实现门户游客实时统计功能

    基于netty+websocket实现门户游客实时统计功能 基本需求 商城门户页面需要实时展示游客访问的数量,商城后台页面需要实时游客访问量.登录用户数量,以及下订单用户数量. 技术选型 1.首先实时 ...

  7. 这么说吧,Netty很简单,其实就是个Jar包,是作为通讯组件用的

    极简教程,五分钟快速入门之netty,搭配后面netty实战以及netty源码分析 0 ) 关键词: Netty.NIO.异步.通讯. 1)本质: 一个Jar包,一个NIO框架,是对 socket 网 ...

  8. 简易 IM 双向通信电脑端 GUI 应用——基于 Netty、WebSocket、JavaFX 、多线程技术等

    简易 IM 双向通信电脑端 GUI 应用--基于 Netty.WebSocket.JavaFX .多线程技术等 说明 运行效果 核心代码 完整代码 参考知识 说明   这是一款使用 Netty 来实现 ...

  9. netty 游戏服务器框图_基于Netty和WebSocket协议实现Web端自动打印订单服务方法与流程...

    本发明涉及电子商务技术领域,尤其涉及一种基于netty和websocket协议实现web端自动打印订单服务方法. 背景技术: 电子商务是以信息网络技术为手段,以商品交换为中心的商务活动:也可理解为在互 ...

最新文章

  1. Git的工作区与暂存区
  2. linux mysql忘记root_linux下mysql-5.6忘记root密码,重置root密码详细过程
  3. Codeforces Round #552 (Div. 3) —— B. Make Them Equal
  4. 智慧城市知识图谱模型与本体构建方法
  5. 诗与远方:无题(七十二)
  6. c#语言程序设计上机实验,《C#语言程序设计》实 验 报 告
  7. mysql-connector-java-5.1.22下载
  8. zabbix-proxy+cacti+nagios基本安装配置
  9. 抖音快闪PPT制作教程
  10. 微信小程序--获取已发布微信小游戏和小程序源码
  11. 火车头采集优化-收集的文章内容怎么批量变成原创文章
  12. 深夜扒一扒Android的发展史
  13. 报错:For input string
  14. 支付宝原生组件(酒店时间选择)
  15. one 主格 复数 宾格_英语主格宾格形容词性物主代词及名词性物主代词练习题.doc...
  16. 我的阿里巴巴一日游,入职当天即提辞职
  17. 在win10子系统ubuntu平台下使用jekyll和github pages搭建自己的静态博客网站
  18. 〖NOIP2004P〗FBI树
  19. 购买老域名,利用桔子seo来查找域名的历史快照信息
  20. Cloud computing application development Topic | Cloud computing

热门文章

  1. Android studio编译很久 Gradle Build Running特别慢问题解决
  2. 贝达药业拟在香港上市:超90%收入来自埃克替尼,市值已大幅缩水
  3. html编码后台转换,html unicode编码转换方法
  4. c语言每个字符占10个字符位左对齐,C语言考前复习资料
  5. 数字电视技术英文专业词汇释义
  6. PVCBOT【15号A版】机械昆虫--六足爬行机器人
  7. 评价方法-层次分析法确定指标权重
  8. rx580 8g显卡相当于什么n卡 rx580 8g属于什么级别的
  9. 物联网开发笔记(26)- 使用Micropython开发ESP32开发板之控制LCD1602显示屏(续)
  10. 《Python数据分析与挖掘实战》张良均,第一章学习笔记