Netty的官方講解:
*[The Netty project](http://netty.io/)* is an effort to provide an asynchronous event-driven network application framework and tooling for the rapid development of maintainable high-performance · high-scalability protocol servers and clients.
In other words, Netty is an NIO client server framework that enables quick and easy development of network applications such as protocol servers and clients. It greatly simplifies and streamlines network programming such as TCP and UDP socket server development.
'Quick and easy' does not mean that a resulting application will suffer from a maintainability or a performance issue. Netty has been designed carefully with the experiences earned from the implementation of a lot of protocols such as FTP, SMTP, HTTP, and various binary and text-based legacy protocols. As a result, Netty has succeeded to find a way to achieve ease of development, performance, stability, and flexibility without a compromise.
Some users might already have found other network application framework that claims to have the same advantage, and you might want to ask what makes Netty so different from them. The answer is the philosophy it is built on. Netty is designed to give you the most comfortable experience both in terms of the API and the implementation from the day one. It is not something tangible but you will realize that this philosophy will make your life much easier as you read this guide and play with Netty.
Netty是由JBOSS提供的一個(gè)java開(kāi)源框架歹河。Netty 是一個(gè)基于NIO的客戶重窟、服務(wù)器端編程框架,Netty提供異步的施绎、事件驅(qū)動(dòng)的網(wǎng)絡(luò)應(yīng)用程序框架和工具酝静,用以快速開(kāi)發(fā)高性能、高可靠性的網(wǎng)絡(luò)服務(wù)器和客戶端程序dsf狼忱。
NIO:是一種同步非阻塞的I/O模型膨疏,也是I/O多路復(fù)用的基礎(chǔ),已經(jīng)被越來(lái)越多地應(yīng)用到大型應(yīng)用服務(wù)器藕赞,成為解決高并發(fā)與大量連接成肘、I/O處理問(wèn)題的有效方式。
NIO一個(gè)重要的特點(diǎn)是:socket主要的讀斧蜕、寫(xiě)双霍、注冊(cè)和接收函數(shù),在等待就緒階段都是非阻塞的批销,真正的I/O操作是同步阻塞的(消耗CPU但性能非常高)
Java NIO淺析:https://mp.weixin.qq.com/s/HhwaXd8x7zONr8N1ojSnsQ?
Netty 能做什么: https://www.zhihu.com/question/24322387/answer/78947405
tinker的Mars框架和Netty框架類似, 但是Mars需要READ_PHONE_STATE等權(quán)限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
如果您的App需要上傳到google play store洒闸,您需要將READ_PHONE_STATE權(quán)限屏蔽掉或者移除,否則可能會(huì)被下架(歐盟數(shù)據(jù)保護(hù)條例)均芽。
心跳檢測(cè)機(jī)制:
1.繼承SimpleChannelInboundHandler,當(dāng)客戶端的所有ChannelHandler中指定時(shí)間內(nèi)沒(méi)有write事件丘逸,則會(huì)觸發(fā)userEventTriggered方法(心跳超時(shí)事件)
//利用寫(xiě)空閑發(fā)送心跳檢測(cè)消息
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent) {
IdleStateEvent e = (IdleStateEvent) evt;
if (event.state() == IdleState.WRITER_IDLE) {
// TODO: 2018/6/13
//ctx.writeAndFlush(HEARTBEAT_SEQUENCE.duplicate()).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
}
}
//連接成功觸發(fā)channelActive
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
listener.onStateChanged(NettyListener.STATE_CONNECT_SUCCESS);
}
//斷開(kāi)連接觸發(fā)channelInactive
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
// TODO: 2018/6/13 重連操作
}
//客戶端收到消息
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, String byteBuf) throws Exception {
//通過(guò)接口將值傳出去
listener.onMessageRes(byteBuf);
}
//異常回調(diào),默認(rèn)的exceptionCaught只會(huì)打出日志掀宋,不會(huì)關(guān)掉channel
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
listener.onStateChanged(NettyListener.STATE_CONNECT_ERROR);
cause.printStackTrace();
ctx.close();
}
2.實(shí)現(xiàn)ChannelInboundHandlerAdapter
import java.util.Date;
public class TimeClientHandler extends ChannelInboundHandlerAdapter {
private ByteBuf buf;
@Override
public void handlerAdded(ChannelHandlerContext ctx) {
buf = ctx.alloc().buffer(4); // (1)
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) {
buf.release(); // (1)
buf = null;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ByteBuf m = (ByteBuf) msg;
buf.writeBytes(m); // (2)
m.release();
if (buf.readableBytes() >= 4) { // (3)
ctx.close();
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
3.創(chuàng)建EventLoopGroup線程組和Bootstrap(Bootstrap 是 Netty 提供的一個(gè)便利的工廠類,通過(guò)Bootstrap 來(lái)完成 Netty 的客戶端或服務(wù)器端的 Netty 初始化.)
EventLoopGroup group = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap().group(group)
//禁用nagle算法 Nagle算法就是為了盡可能發(fā)送大塊數(shù)據(jù)深纲,避免網(wǎng)絡(luò)中充斥著許多小數(shù)據(jù)塊仲锄。
.option(ChannelOption.TCP_NODELAY, true)//屏蔽Nagle算法試圖
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
//指定NIO方式 //指定是NioSocketChannel, 用NioSctpChannel會(huì)拋異常
.channel(NioSocketChannel.class)
//指定編解碼器,處理數(shù)據(jù)的Handler
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new IdleStateHandler(0, 5, 0, TimeUnit.SECONDS));//5s未發(fā)送數(shù)據(jù)湃鹊,回調(diào)userEventTriggered
socketChannel.pipeline().addLast(new LineBasedFrameDecoder(1024));
socketChannel.pipeline().addLast(new StringDecoder(CharsetUtil.UTF_8));
socketChannel.pipeline().addLast(new StringEncoder(CharsetUtil.UTF_8));
socketChannel.pipeline().addLast(new TimeServerHandler());
socketChannel.pipeline().addLast(new HeartbeatServerHandler());
socketChannel.pipeline().addLast(new NettyClientHandler(nettyListener));
// Packet packet = Packet.newInstance();
// byte[] bytes = packet.packetHeader(20, 0x100, (short) 200, (short) 0, (short) 1, 1, 0);
}
});
4.連接服務(wù)器的host和port
channelFuture = bootstrap.connect(host,tcp_port).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture channelFuture) throws Exception {
if (channelFuture.isSuccess()) {
//連接成功
channel = channelFuture.channel();
} else {
//連接失敗
}
}
}).sync();
channelFuture.channel().closeFuture().sync();
Log.e(TAG, " 斷開(kāi)連接");
5.連接成功后,向服務(wù)器發(fā)送信息
channel.writeAndFlush("你要發(fā)送的信息").addListener(listener);
6.斷開(kāi)關(guān)閉連接
if (null != channelFuture) {
if (channelFuture.channel() != null && channelFuture.channel().isOpen()) {
channelFuture.channel().close();
}
}
group.shutdownGracefully();
7.Channel使用完畢后儒喊,一定要調(diào)用close(),釋放通道占用的資源币呵。
8.結(jié)合Service被忱ⅲ活,實(shí)現(xiàn)Socket長(zhǎng)連接
《Android應(yīng)用進(jìn)程防殺死》: http://www.reibang.com/p/22a708c74c1e
相關(guān)鏈接:
jar下載地址:http://netty.io/downloads.html
netty官方地址: http://netty.io/
netty4.x 官方地址:http://netty.io/wiki/user-guide-for-4.x.html
Netty 實(shí)現(xiàn)聊天功能:https://waylau.com/netty-chat/
netty實(shí)現(xiàn)長(zhǎng)連接心跳檢: https://blog.csdn.net/qq_19983129/article/details/53025732