netty4 Android和服务器进行通信
来源:互联网 发布:not close json text 编辑:程序博客网 时间:2024/04/28 19:03
原本公司用的是极光推送消息。但是由于公司网络原因,或者说是极光推送的不及时性,BOSS说太慢,就让改成长链接了,花费了几天时间查资料,总算搞懂了一点皮毛,简单的通讯已经不是问题了。今天下午无事,写点内容巩固写记忆。我负责的Android这边。所以服务器的那边的不太会。netty的版本是netty-4.0.31.Final。。
一。服务端代码
这里是主要代码。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)); //下面注释的两行是加密和解密。服务器和客户端需要统一 //不然会报错。所以我直接注释了。 /*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
0 0
- netty4 Android和服务器进行通信
- 使用netty4 和 protobuf2.6.1进行网络通信
- android如何使用bks和apache服务器进行https通信
- Android和服务器通信
- 使用 java.io 进行服务器-Android通信
- Android客户端与服务器进行通信
- Android通过Socket与服务器进行通信
- XMLHttpRequest对象来和服务器进行通信
- Android客户端和服务器通信
- netty4通信步骤,原理
- C++和android进行socket通信小结
- Android碎片和活动之间进行通信
- Android中Intent和IntentFilter进行通信
- **ANDROID**Intent和IntentFilter的进行通信
- Android入门:通过XML数据与服务器进行通信
- Android入门:通过JSON数据与服务器进行通信
- Android入门:通过XML数据与服务器进行通信
- Android入门:通过JSON数据与服务器进行通信
- iOS AutoLayout自动布局中级开发教程(3)-等宽等高等中心
- Android如何设置TextView的行间距、行高
- 8、表单(二)、CSS
- OpenGL教程翻译 第二十一课 聚光灯
- 99表
- netty4 Android和服务器进行通信
- 第四周上机实践—项目3(2)—单链表的应用 实现算法并分析复杂度
- delphi线程中操作access数据库经常报内存地址错误解决方法
- PPL 和AMP并行编程
- BZOJ 3991: [SDOI2015]寻宝游戏
- linux Read命令
- opengl中的三维数学一(基础三维讲解)
- 字符串匹配的KMP算法
- 猴子数数问题