java websocket netty
netty-maven
<!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.6.Final</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20150729</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
<!-- log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
Log4J
String workpath = System.getProperty("user.dir");
try {
PropertyConfigurator.configure(new File(workpath, "log4j.properties").getCanonicalPath());
} catch (IOException e1) {
e1.printStackTrace();
}
log4j.rootLogger=INFO,A1
# A1 is set to be a ConsoleAppender which outputs to System.out.
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
#log4j.appender.A1.layout.ConversionPattern=%-4r %-2p [%t] [%37c] [%3x] %m%n
log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%p][%t][%c] %m%n
log4j.logger.test=DEBUG
Netty-websocket
public void serverLoop() throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new HttpServerCodec());
pipeline.addLast(new HttpObjectAggregator(65535));
//这是超时逻辑 readerIdleTime 秒
pipeline.addFirst(new IdleStateHandler(readerIdleTime, 0, 0, TimeUnit.SECONDS));
pipeline.addLast(new WebSocketServerCompressionHandler());
//ws://local:port/Test 一个数据包最大1M
pipeline.addLast(new WebSocketServerProtocolHandler("/Test", null, false, 1024 * 1024));
pipeline.addLast("handler", new WebSocketServerHandler(manager, handler));
}
}).option(ChannelOption.SO_BACKLOG, 128) // (5)
.childOption(ChannelOption.SO_KEEPALIVE, true); // (6)
f = b.bind(port).sync(); // (7)WebSocket08FrameDecoder
System.out.println("bind "+this.port);
f.channel().closeFuture().sync();
System.out.println("quit");
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
Websocket数据处理
public class WebSocketServerHandler extends SimpleChannelInboundHandler<Object> {
//异常
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
logger.debug("--->exception:" + ctx.channel() + cause.getMessage());
cause.printStackTrace();
ctx.close();
}
//连接成功
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception { // (5)
Channel channel = ctx.channel();
logger.debug("Channel:" + channel.id() + "," + channel.remoteAddress() + ", 在线");
ByteArrayOutputStream out = new ByteArrayOutputStream();
channel.attr(KEY_Base).set(new WebSocketSession());
}
//离线
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception { // (6)
Channel channel = ctx.channel();
NetSession session = channel.attr(KEY_session).get();
logger.debug("Channel:" + channel.id() + "," + channel.remoteAddress() + "," + "掉线 ");
}
//超时: 需要 IdleStateHandler
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent) {
IdleStateEvent event = (IdleStateEvent) evt;
if (event.state() == IdleState.READER_IDLE) {
/* 读超时 */
logger.debug("Channel: timeout");
ctx.channel().close();
} else if (event.state() == IdleState.WRITER_IDLE) {
} else if (event.state() == IdleState.ALL_IDLE) {
/* 总超时 */
}
}
super.userEventTriggered(ctx, evt);
}
//读取到数据
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
//需要进行缓冲处理继续帧,未帧
WebSocketSession webSocketSession = ctx.channel().attr(KEY_Base).get();
if (msg instanceof TextWebSocketFrame) {
System.out.println("收到消息:" + ((TextWebSocketFrame) msg).text());
} else if (msg instanceof BinaryWebSocketFrame) {
BinaryWebSocketFrame bmsg = (BinaryWebSocketFrame) msg;
webSocketSession.appendBuf(bmsg.content());
if (bmsg.isFinalFragment())
channelHandleMsg(ctx, webSocketSession);
} else if (msg instanceof ContinuationWebSocketFrame) {
ContinuationWebSocketFrame cmsg = (ContinuationWebSocketFrame) msg;
// logger.debug("继续帧:{}, {}", cmsg.isFinalFragment(),cmsg.content().capacity());
webSocketSession.appendBuf(cmsg.content());
if (cmsg.isFinalFragment())
channelHandleMsg(ctx, webSocketSession);
}
}
ByteBuf操作
不说