闲来无事,朋友问用过netty框架没有,心一想,之前用过socket,mqtt,mina唯独没有用过netty,不妨来看一下,借鉴朋友的Demo,顺便改了一下
测试工具下载地址
https://pan.baidu.com/s/1PZc9mnlvRZ-KDpjV2sT8NA
提取码:lc83
注意:
a、在测试工具中发送数据到Android客户端,Android客户端可能会收不到服 务端发送的消息,这是因为你没有选中要发送给哪个客户端,在测试工具中的当前连接面板中,选中你要发送给哪个客户端,然后再发送数据就ok,操作问题,并非代码问题!
b、如果用真机连接的测试,可能会出现连接不上电脑上的测试工具,注意这个时候需要考虑下真机和电脑端是否处于同一个网段内,我在测试过程中出现了这一问题,把测试环境改为模拟器测试就可以跑通了!
c、测试请更换为自己的ip和port
1、用到的netty库
implementation 'io.netty:netty-all:4.1.23.Final'
2、核心连接部分,代码就不全部贴出来了,需要的话在下方我会分享码云上的demo源码
public void connect() {
if (isConnecting) {
return;
}
//起个线程
Thread clientThread = new Thread("client-Netty") {
@Override
public void run() {
super.run();
isNeedReconnect = true;
reconnectNum = Integer.MAX_VALUE;
connectServer();
}
};
clientThread.start();
}
//连接时的具体参数设置
private void connectServer() {
synchronized (NettyClient.this) {
ChannelFuture channelFuture = null;//连接管理对象
if (!isConnect) {
isConnecting = true;
group = new NioEventLoopGroup();//设置的连接group
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)//设置的一系列连接参数操作等
.channel(NioSocketChannel.class)
.handler(new NettyClientHandler(listener));
try {
//连接监听
channelFuture = bootstrap.connect(Constans.HOST, Constans.TCP_PORT).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture channelFuture) throws Exception {
if (channelFuture.isSuccess()) {
isConnect = true;
channel = channelFuture.channel();
} else {
EventBus.getDefault().post(new MainMsg("连接失败"));
Log.e(TAG, "连接失败");
isConnect = false;
}
isConnecting = false;
}
}).sync();
// 等待连接关闭
channelFuture.channel().closeFuture().sync();
Log.e(TAG, " 断开连接");
} catch (Exception e) {
Log.e(TAG, "e:" + e.toString());
e.printStackTrace();
} finally {
isConnect = false;
listener.onServiceStatusConnectChanged(NettyListener.STATUS_CONNECT_CLOSED);//STATUS_CONNECT_CLOSED 这我自己定义的 接口标识
if (null != channelFuture) {
if (channelFuture.channel() != null && channelFuture.channel().isOpen()) {
channelFuture.channel().close();
}
}
group.shutdownGracefully();
reconnect();//重新连接
}
}
}
}
public class NettyClientHandler extends ChannelInboundHandlerAdapter {
private static final String TAG = NettyClientHandler.class.getSimpleName();
private NettyListener listener;
public NettyClientHandler(NettyListener listener) {
this.listener = listener;
}
//每次给服务器发送的东西, 让服务器知道我们在连接中哎
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent) {
IdleStateEvent event = (IdleStateEvent) evt;
if (event.state() == IdleState.WRITER_IDLE) {
ctx.channel().writeAndFlush("Heartbeat");
}
}
}
/**
* 连接成功
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
listener.onServiceStatusConnectChanged(NettyListener.STATUS_CONNECT_SUCCESS);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
super.channelInactive(ctx);
Log.e(TAG, "channelInactive");
}
//接收消息的地方, 接口调用返回到activity了
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
listener.onMessageResponse(msg);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
// 当引发异常时关闭连接。
EventBus.getDefault().post(new MainMsg("引发异常,关闭连接:" + cause.toString()));
Log.e(TAG, "引发异常,关闭连接:" + cause.toString());
listener.onServiceStatusConnectChanged(NettyListener.STATUS_CONNECT_ERROR);
cause.printStackTrace();
ctx.close();
}
}
Demo下载地址:https://gitee.com/wasadsdfa/NettyDemo
如有问题欢迎指出