android netty导入_Android实现服务端与客户端netty交互(windows)包括部分问题及解决方案...

本文记录了Android环境下使用Netty进行服务端与客户端交互遇到的问题及解决方案,包括NoClassDefFoundError、Android版本适配、Activity错误、不同Activity间共享连接、数据发送与接收等问题,提供了具体的解决方法和示例代码。
摘要由CSDN通过智能技术生成

---------------2020-3-14初次记录

初入Netty,了解参考:跳转

服务端使用eclipse,客户端使用android studio3.5.2:

代码参考:跳转包括(环境搭建)

服务端客户端均在eclipse,代码参考:跳转

后期待修补(android studio测试可运行,但是我的netty版本以及as的SDK版本及真机测试API版本有问题,待修补)。

---------------2020-3-15更新

因为昨日在android测试的时候出现了很多问题,今天解决了挺多,在此记录一下问题与解决方案。

前提:

我的as版本3.5.2,compilesdkversion 8.0,targetsdkversion 8.0,compiletoolversion 29.0.2,客户端netty版本4.1.11,真机测试android 7& android9

1:在创建连接的代码处:group = new NioEventLoopGroup();报错:No class deffound error log/apache/loging/log4J2Logger.....

问题原因:因为当时我用的netty版本是4.5.x,总之比4.1.11版本高,我尝试import这个类,果然没有,我觉得是包的问题。

问题解决:重新导入了4.1.11版本的netty包,问题解决。

在此额外提一句,如果是as由原来的包更换的话,注意把之前的依赖项给remove,如果是通过maven-Gradle导入的包,现在的好像自动移除之前的依赖,问题可能会出现在你通过jar包添加的依赖!

2:纯属我的as问题:在activity的代码处:setContentView(R.layout.activity_sign); 报错:java.lang.ClassNotFoundException: Didn't find class "android.view.View$OnUnhandledKeyEventListener" on path: DexPathList[[zip file "/data/app/com.example.login_server-2/base.apk"],nativeLibraryDirectories=[/data/app/com.example.login_server-2/lib/arm64, /data/app/com.example.login_server-2/base.apk!/lib/arm64-v8a, /system/lib64, /vendor/lib64]]

问题原因:因为系统编译版本更新以后,编译工具都是29的了,而我的android真机还是7.0,API24所以对比起来差了很多,以前我跑这个真机从来每出现过。。。

问题解决:我用android9的真机测试了一下,把targetversion和compileversion改为28,tool还是29.0.2好歹还接近一点28,就没有这个问题了,对于这个问题的解决方案是忽视:事实上即使提醒了,这个问题至目前为止除了报错还没有出现其他问题,后期也考虑使用android9手机测试。如果你尝试将gradle中的targetversion和compileversion改为24,那不行,除非你的tool有低版本的。。。我最低的就是28.0了(哭泣! 而且谷歌那边好像要求targetversion最低26..

---------2020-3-17 我来更新这个问题啦,在昨晚上跑系统的时候一如既往地报这个错误(问题2),我突然注意到错误里面提到了AppcompatActivity,众所周知,activity要么extends AppcompatActivity要么extends activity,于是我怀疑是不是因为不能集成AppcompatActivity的原因,因为我一直继承的AppcompatActivity,只有单独使用button的on click方法时才考虑更换。--3-18 我又来了,如果你的activity里面有图片(drawable)那此解决方法无效。

解决方法:将activity的继承更改为Activity,就不再报这个错误!!!(也许仅适用于我的module...  maybe you can try it....

3:在一个activity使用netty连接上服务端后,在另一个activity获取之前连接的channel(来自自定义类--用于连接服务端,获取channel等等,但是获取到的channel为空,也就是没有连接???我的服务端显示已经连接上了!

问题原因:因为我在不同的activity中都创建了自定义类的对象,既然是不同对象,里面的类型值自然不一样,自然不能有B这个对象获取A这个对象之前保存的值!

问题解决:自定义了一个类,设置static channel值,连接上服务端后就setchannel,其他activity获取值也从这里面直接拿就行,测试可行,代码在后面有。

4:连接成功发送数据失败:1)注意你的结束符设置的是什么?发送的数据要以你设置的为准。2)如果你的测试代码里面连接之后就是发送信息,很有可能出现你还没连接上,就开始跑发送数据这块代码,我jio得可能因为子线程跑完在跑的同时,按顺序执行代码也在继续,就出现这个问题了!注意在连接之后再发送数据,或者直接在你的连接里面发数据也可以。

5:服务端返回信息给客户,客户获取并发送至activity:可以使用handle,突然想到一个问题,如果发送到其他普通类呢?emmmm待解决。

6:因为我在项目中加密了一些数据,加密后的数据包含换行符('\n')需要发到服务端,而我初始化的发送数据以换行符为结束符,这样我服务端就无法收到完整正确的数据了!

问题原因:自定义结束符为\n。

问题解决:修改结束符为$E$,貌似$是特殊字符一般不会在加密后的数据中出现!

7:activity中的AlertDialog定义后调用不弹出!

我的链接(单独开出来一个随笔嘿嘿嘿

我的代码(客户端),仅供参考:

nettyTcpThread:连接服务端

1 packagecom.example.login_server.netty;2

3 importandroid.util.Log;4

5 importio.netty.bootstrap.Bootstrap;6 importio.netty.channel.Channel;7 importio.netty.channel.ChannelFuture;8 importio.netty.channel.ChannelOption;9 importio.netty.channel.EventLoopGroup;10 importio.netty.channel.nio.NioEventLoopGroup;11 importio.netty.channel.socket.nio.NioSocketChannel;12

13 /**

14 *2020-3-1515 * by Zhang Liling16 **/

17 public classnettyTcpThread {18 private String TAG = "nettyTcpClient";19 private String mIp = "XXX,XXX,XX,XX"; //插入你的ip地址

20 private int mPort = 7327;21

22 privateChannel mChannel;23 privateEventLoopGroup group;24

25 public voidstartConnect(){26 if(nettyChannelFuture.getIsConnect()){27 return;28 }29 group = newNioEventLoopGroup();30 try{31 Bootstrap clientBootStrap = newBootstrap();32 clientBootStrap.group(group)33 .channel(NioSocketChannel.class)34 .option(ChannelOption.TCP_NODELAY,true) //屏蔽Nagle算法试图

35 .option(ChannelOption.CONNECT_TIMEOUT_MILLIS,5000)36 .handler(newClientInitializer());37 ChannelFuture future =clientBootStrap.connect(mIp, mPort).sync();38 mChannel =future.channel();39 nettyChannelFuture.setChannel(mChannel);40 nettyChannelFuture.setGroup(group);41 nettyChannelFuture.setIsConnect(true);42 Log.i(TAG,"已连接到服务器!");43

44 mChannel.closeFuture().sync();45 Log.i(TAG,"已从服务器断开");46 }catch(InterruptedException e){47 e.printStackTrace();48 }finally{49 group.shutdownGracefully();50 }51 }52

53 //发起连接&发送数据data

54 public voidstartConnectSendData(String data){55 if(nettyChannelFuture.getIsConnect()){56 return;57 }58 group = newNioEventLoopGroup();59 try{60 Bootstrap clientBootStrap = newBootstrap();61 clientBootStrap.group(group)62 .channel(NioSocketChannel.class)63 .option(ChannelOption.TCP_NODELAY,true) //屏蔽Nagle算法试图

64 .option(ChannelOption.CONNECT_TIMEOUT_MILLIS,5000)65 .handler(newClientInitializer());66 ChannelFuture future =clientBootStrap.connect(mIp, mPort).sync();67 mChannel =future.channel();68 nettyChannelFuture.setChannel(mChannel);69 nettyChannelFuture.setGroup(group);70 nettyChannelFuture.setIsConnect(true);71 Log.i(TAG,"已连接到服务器!");72 mChannel.writeAndFlush(data+"\n");73

74 mChannel.closeFuture().sync();75 Log.i(TAG,"已从服务器断开");76 }catch(InterruptedException e){77 e.printStackTrace();78 }finally{79 group.shutdownGracefully();80 }81 }82

83 public void sendMsg(Channel channel, finalString data){84 if(channel != null){85 channel.writeAndFlush(data+"\n");86 }else{87 newThread(){88 @Override89 public voidrun() {90 startConnectSendData(data);91 }92 }.start();93 }94 }95

96 public voiddisconnect(Channel channel){97 if(channel != null){98 channel.close();99 Log.e(TAG,"disconnect");100 nettyChannelFuture.setIsConnect(false);101 }else{102 Log.i(TAG,"channel已断开连接");103 }104 }105

106 }

nettyTcpThread

ClientInitializer :设置channel参数

1 packagecom.example.login_server.netty;2

3 importio.netty.channel.Channel;4 importio.netty.channel.ChannelInitializer;5 importio.netty.channel.ChannelPipeline;6 importio.netty.handler.codec.DelimiterBasedFrameDecoder;7 importio.netty.handler.codec.Delimiters;8 importio.netty.handler.codec.string.StringDecoder;9 importio.netty.handler.codec.string.StringEncoder;10 importio.netty.util.CharsetUtil;11 /**

12 *2020-3-1513 * by Zhang Liling14 **/

15 public class ClientInitializer extendsChannelInitializer {16 @Override17 protected void initChannel(Channel ch) throwsException {18 ChannelPipeline pipeline =ch.pipeline();19 pipeline20 .addLast("framer",new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()))21 .addLast("decoder",newStringDecoder(CharsetUtil.UTF_8))22 .addLast("encoder",newStringEncoder(CharsetUtil.UTF_8))23 .addLast("handler",newEchoClientHandler());24 }25 }

ClientInitializer

EchoClientHandler:处理返回数据

1 packagecom.example.login_server.netty;2

3 importandroid.os.Bundle;4 importandroid.os.Message;5 importandroid.util.Log;6

7 importcom.example.login_server.loginInfo.MainActivity;8

9 importio.netty.channel.ChannelHandlerContext;10 importio.netty.channel.SimpleChannelInboundHandler;11 /**

12 *2020-3-1513 * by Zhang Liling14 **/

15 public class EchoClientHandler extends SimpleChannelInboundHandler{16 private String TAG = "EchoClientHandler";17 @Override18 public void channelActive(ChannelHandlerContext ctx) throwsException {19 super.channelActive(ctx);20 }21

22 @Override23 public void channelInactive(ChannelHandlerContext ctx) throwsException {24 super.channelInactive(ctx);25 }26

27 privateString getmsg(String data,String msg){28 String getmsg = null;29 String[] data0 = data.split(msg+"=");30 if(data0!=null && data0.length > 1){31 String[] data1 = data0[1].split(";");32 getmsg = data1[0];33 }34 returngetmsg;35 }36

37 @Override38 protected void channelRead0(ChannelHandlerContext channelHandlerContext, String data) throwsException {39 //处理data

40 manageData(data);41

42 Log.i(TAG,"received msg from server:" +data);43 }44

45 private voidmanageData(String data) {46 String req="";47 req = getmsg(data,"res");48 if(req.equals("login")){49 String myname = "";50 myname = getmsg(data,"myname");51 Message message = newMessage();52 message.what=MainActivity.RECNAME_LOGIN;53 Bundle bundle = newBundle();54 bundle.putString("msg",myname);55 message.setData(bundle);56 MainActivity.getMainActivity().getMsghandler().sendMessage(message);57 }else if(req.equals("loginmyinfo")){58 Message message = newMessage();59 message.what=MainActivity.RECINFO_LOGIN;60 Bundle bundle = newBundle();61 bundle.putString("pubkey",getmsg(data,"pubkey"));62 bundle.putString("seckey",getmsg(data,"seckey"));63 message.setData(bundle);64 MainActivity.getMainActivity().getMsghandler().sendMessage(message);65

66 }67 }68

69 @Override70 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throwsException {71 cause.printStackTrace();72 ctx.close();73 }74 }

EchoClientHandler

nettyChannelFuture:存储变量供其他类连接使用

1 packagecom.example.login_server.netty;2

3 importio.netty.channel.Channel;4 importio.netty.channel.EventLoopGroup;5 /**

6 *2020-3-157 * by Zhang Liling8 **/

9 public classnettyChannelFuture {10 private staticChannel mchannel;11 private staticEventLoopGroup mgroup;12 private static booleanmisConnect;13

14 public static void setIsConnect(booleanisConnect) {15 misConnect =isConnect;16 }17

18 public static booleangetIsConnect() {19 returnmisConnect;20 }21

22 public static voidsetGroup(EventLoopGroup group) {23 mgroup =group;24 }25

26 public static voidsetChannel(Channel channel) {27 mchannel =channel;28 }29

30 public staticChannel getChannel(){31 returnmchannel;32 }33

34 public staticEventLoopGroup getGroup(){35 returnmgroup;36 }37 }

nettyChannelFuture

T

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值