netty4 Android和服务器进行通信
2015-09-30 14:35
435 查看
原本公司用的是极光推送消息。但是由于公司网络原因,或者说是极光推送的不及时性,BOSS说太慢,就让改成长链接了,花费了几天时间查资料,总算搞懂了一点皮毛,简单的通讯已经不是问题了。今天下午无事,写点内容巩固写记忆。我负责的Android这边。所以服务器的那边的不太会。netty的版本是netty-4.0.31.Final。。
服务端代码2。
这里的代码就是简单启动一下长链接。。
这里是运行效果。。
最后加上代码下载链接。还有一份java客户端的。不过是很简单的。
http://download.csdn.net/detail/a466125796/9149831
一。服务端代码
这里是主要代码。NettyServerHandler()方法主要是进行发送消息和接受消息的操作。public class NettyServerBootstrap { private int port; public NettyServerBootstrap(int port) throws InterruptedException { this.port = port; bind(); } private void bind() throws InterruptedException { EventLoopGroup boss=new NioEventLoopGroup(); EventLoopGroup worker=new NioEventLoopGroup(); ServerBootstrap bootstrap=new ServerBootstrap(); bootstrap.group(boss,worker); bootstrap.channel(NioServerSocketChannel.class); bootstrap.option(ChannelOption.SO_BACKLOG, 128); //通过NoDelay禁用Nagle,使消息立即发出去,不用等待到一定的数据量才发出去 bootstrap.option(ChannelOption.TCP_NODELAY, true); //保持长连接状态 bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true); bootstrap.childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { ChannelPipeline p = socketChannel.pipeline(); /* p.addLast(new ObjectEncoder()); p.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(null)));*/ p.addLast(new NettyServerHandler()); } }); ChannelFuture f= bootstrap.bind(port).sync(); if(f.isSuccess()){ System.out.println("server start---------------"); } } //开启服务器端口监听 public static void main(String []args) throws InterruptedException { NettyServerBootstrap bootstrap=new NettyServerBootstrap(9999); /*while (true){ SocketChannel channel=(SocketChannel)NettyChannelMap.get("001"); if(channel!=null){ AskMsg askMsg=new AskMsg(); channel.writeAndFlush(askMsg); } TimeUnit.SECONDS.sleep(5); }*/ } }
服务端代码2。
public class NettyServerHandler extends SimpleChannelInboundHandler<Object> { @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { //channel失效,从Map中移除 NettyChannelMap.remove((SocketChannel)ctx.channel()); } //这里是从客户端过来的消息 @Override protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object baseMsg) throws Exception { System.out.println("收到没有"); //传送的消息是ByteBuf格式的。所以不管发送还是接收都需要转化 String msg1=((ByteBuf)baseMsg).toString(CharsetUtil.UTF_8).trim(); System.out.println(msg1); //ReferenceCountUtil.release(baseMsg); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)throws Exception { super.exceptionCaught(ctx, cause); System.out.println("出现异常了。"); } }
二。客户端代码
客户端代码和服务端基本属于一样的结构。public class NettyClientBootstrap { private int port=9999; private String host="192.168.1.186"; public SocketChannel socketChannel; public void startNetty() throws InterruptedException { System.out.println("长链接开始"); if(start()){ System.out.println("长链接成功"); ByteBuf bb = Unpooled.wrappedBuffer(("tableIP=asdf".getBytes(CharsetUtil.UTF_8))); socketChannel.writeAndFlush(bb); } } private Boolean start() throws InterruptedException { EventLoopGroup eventLoopGroup=new NioEventLoopGroup(); Bootstrap bootstrap=new Bootstrap(); bootstrap.channel(NioSocketChannel.class); bootstrap.option(ChannelOption.SO_KEEPALIVE,true); bootstrap.group(eventLoopGroup); bootstrap.remoteAddress(host, port); bootstrap.handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast(new IdleStateHandler(20, 10, 0)); //下面注释的两行是加密和解密。服务器和客户端需要统一 / 4000 /不然会报错。所以我直接注释了。 /*socketChannel.pipeline().addLast(new ObjectEncoder()); socketChannel.pipeline().addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(null)));*/ socketChannel.pipeline().addLast(new NettyClientHandler()); } }); ChannelFuture future = null ; try { future =bootstrap.connect(new InetSocketAddress(host,port)).sync(); if (future.isSuccess()) { socketChannel = (SocketChannel)future.channel(); System.out.println("connect server 成功---------"); return true; }else{ System.out.println("connect server 失败---------"); startNetty(); return false; } } catch (Exception e) { System.out.println("无法连接----------------"); //这里最好暂停一下。不然会基本属于毫秒时间内执行很多次。 //造成重连失败 TimeUnit.SECONDS.sleep(5); startNetty(); return false; } } }
public class NettyClientHandler extends SimpleChannelInboundHandler<Object> { //设置心跳时间 开始 public static final int MIN_CLICK_DELAY_TIME = 1000*30; private long lastClickTime =0; //设置心跳时间 结束 //利用写空闲发送心跳检测消息 @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof IdleStateEvent) { IdleStateEvent e = (IdleStateEvent) evt; switch (e.state()) { case WRITER_IDLE: long currentTime = System.currentTimeMillis(); if(currentTime - lastClickTime > MIN_CLICK_DELAY_TIME){ lastClickTime = System.currentTimeMillis(); ByteBuf bb = Unpooled.wrappedBuffer("ping".getBytes(CharsetUtil.UTF_8)); ctx.writeAndFlush(bb); System.out.println("send ping to server----------"); } break; default: break; } } } //这里是接受服务端发送过来的消息 protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object baseMsg) throws Exception { String msg1=((ByteBuf)baseMsg).toString(CharsetUtil.UTF_8).trim(); System.out.println("1111111111111111------------------------"+msg1); ReferenceCountUtil.release(msg1); } NettyClientBootstrap nettyClient=new NettyClientBootstrap(); //这里是断线要进行的操作 @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { super.channelInactive(ctx); System.out.println("重连了。---------"); //这里最好暂停一下。不然会基本属于毫秒时间内执行很多次。 //造成重连失败 TimeUnit.SECONDS.sleep(5); nettyClient.startNetty(); //ctx.channel().eventLoop().schedule(); } //这里是出现异常的话要进行的操作 @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)throws Exception { super.exceptionCaught(ctx, cause); System.out.println("出现异常了。。。。。。。。。。。。。"); TimeUnit.SECONDS.sleep(10); nettyClient.startNetty(context); cause.printStackTrace(); } }
这里的代码就是简单启动一下长链接。。
public class MainActivity extends Activity { private Button sendButton; NettyClientBootstrap nettyStart=new NettyClientBootstrap(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); sendButton = (Button) findViewById(R.id.btn1); sendButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { nettyStart.startNetty(); } catch (InterruptedException e) { e.printStackTrace(); } } }); } }
这里是运行效果。。
最后加上代码下载链接。还有一份java客户端的。不过是很简单的。
http://download.csdn.net/detail/a466125796/9149831
相关文章推荐
- Android如何设置TextView的行间距、行高
- Android-Universal-Image-Loader不同路径加载图片方式
- Android手势判断
- Android使用Put方式提交数据
- Android系统中Parcelable和Serializable的区别
- android,结合Timer和TimerTask实现定时任务
- Android使用枚举单例实现Toast快速刷新
- android 4.4 状态栏隐藏
- android中代码混淆
- Android studio报错 Error retrieving parent for item: No resource found that matches the given name ...
- android
- android ViewPager滑动事件讲解
- 【Android】解决在Android虚拟机中安装apk报error:protocol faultno status或error:device not found问题
- android-----ListView和GridView的用法
- AndroidStudio快捷键
- android:scrollbarStyle属性
- Android Studio 中ADB WIFI 插件的使用
- Android Studio安装后提示No JVM installation found解决办法
- android 5.1 中添加显示运营商的控制
- android 页面停几秒后跳转