技术标签: Netty 消息协议 Http WebSocket
/*
* 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() {
@Override
protected 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();
}
}
/*
* 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> {
@Override
protected 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)));
}
}
@Override
public void channelActive(ChannelHandlerContext ctx) {
System.out.println("服务器:连接建立");
}
@Override
public void channelInactive(ChannelHandlerContext ctx) {
System.out.println("服务器:断开连接");
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable) {
System.out.println("服务器:异常发送");
throwable.printStackTrace();
}
}
/*
* 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(自己写的类)服务,用于初始化EasyWsHandle
URI wsUri = new URI(uriStr);
WebSocketClientHandshaker webSocketClientHandshaker = WebSocketClientHandshakerFactory
.newHandshaker(wsUri, WebSocketVersion.V13, null, true, new DefaultHttpHeaders(), 100 * 1024 * 1024);
handler = new EasyWsClientHandler(webSocketClientHandshaker);
// 设置Bootstrap
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group);
bootstrap.channel(NioSocketChannel.class);
bootstrap.handler(new ChannelInitializer() {
@Override
protected 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();
}
}
/*
* 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;
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) {
handshakeFuture = ctx.newPromise();
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("客户端连接建立");
// 在通道连接成功后发送握手连接
handshaker.handshake(ctx.channel());
super.channelActive(ctx);
}
@Override
protected 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();
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable arg1) {
System.out.println("异常发生");
arg1.printStackTrace();
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
System.out.println("客户端连接断开");
super.channelInactive(ctx);
}
}
/*
* 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;
@Test
public void startServer() throws Exception {
EasyWsServer easyWsServer = new EasyWsServer(PORT);
easyWsServer.start();
}
@Test
public void startClient() throws Exception {
EasyWsClient easyWsClient = new EasyWsClient(IP, PORT);
easyWsClient.run();
}
}
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包目录下,可以下载查看
文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib
文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang
文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些
文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器
文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距
文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器
文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn
文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios
文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql
文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...
文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120
文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数