您的位置:首页 > 移动开发 > Android开发

netty4 Android和服务器进行通信

2015-09-30 14:35 435 查看
原本公司用的是极光推送消息。但是由于公司网络原因,或者说是极光推送的不及时性,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));
//下面注释的两行是加密和解密。服务器和客户端需要统一
/
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  netty4和安卓