一、先引入依赖,客户端和服务端用的都是同一个依赖netty-all。

  Android Studio中Gradle配置:


compile 'io.netty:netty-all:5.0.0.Alpha2'


  IDEA中Maven配置:


<!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>5.0.0.Alpha2</version>
</dependency>


二、创建消息模块包。

  目前demo中消息包共如下6个类:

1.BaseMsg
 
 
 
  
 BaseMsg 
   2.Constants
 
  
   Constants 
   3.LoginFailMsg
 
  
   LoginFailMsg 
   4.LoginMsg
 
  
   LoginMsg 
   5.MsgType
 
  
   MsgType 
   6.PushMsg
 
  
   PushMsg

 但要注意,客户端包名和服务端包名必须一致,否则会报如下错误:

八月 11, 2016 10:37:57 上午 io.netty.channel.DefaultChannelPipeline$TailContext exceptionCaught
警告:

An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
 io.netty.handler.codec.DecoderException: java.io.InvalidClassException: failed to read class descriptor
 at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:347)
 at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:230)
 at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:84)
 at io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:153)
 at io.netty.channel.PausableChannelEventExecutor.invokeChannelRead(PausableChannelEventExecutor.java:86)
 at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:389)
 at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:956)
 at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:127)
 at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:514)
 at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:471)
 at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:385)
 at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:351)
 at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116)
 at io.netty.util.internal.chmv8.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1412)
 at io.netty.util.internal.chmv8.ForkJoinTask.doExec(ForkJoinTask.java:280)
 at io.netty.util.internal.chmv8.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:877)
 at io.netty.util.internal.chmv8.ForkJoinPool.scan(ForkJoinPool.java:1706)
 at io.netty.util.internal.chmv8.ForkJoinPool.runWorker(ForkJoinPool.java:1661)
 at io.netty.util.internal.chmv8.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:126)
 Caused by: java.io.InvalidClassException: failed to read class descriptor
 at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1604)
 at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)
 at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)
 at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
 at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
 at io.netty.handler.codec.serialization.ObjectDecoder.decode(ObjectDecoder.java:75)
 at io.netty.handler.codec.LengthFieldBasedFrameDecoder.decode(LengthFieldBasedFrameDecoder.java:343)
 at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:316)
 ... 18 more
 Caused by: java.lang.ClassNotFoundException: org.netty.module.LoginMsg
 at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
 at java.lang.Class.forName0(Native Method)
 at java.lang.Class.forName(Class.java:348)
 at io.netty.handler.codec.serialization.ClassLoaderClassResolver.resolve(ClassLoaderClassResolver.java:31)
 at io.netty.handler.codec.serialization.CompactObjectInputStream.readClassDescriptor(CompactObjectInputStream.java:55)
 at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1602)
 ... 25 more

我这里包名统一为org.netty.module。当然我也不百分百确定是不是这个原因,所以如果有了解的望能指点一下。。多谢了!

三、服务端添加Handler,Bootstrap,ChannelMap:

  1.NettyServerHandler,用于进行接收处理客户端消息、断线重连、异常处理等操作。


  NettyServerHandler

2.NettyServerBootstrap引导程序,用于进行启动服务、推送消息、通道操作等操作。


  NettyServerBootstrap

  3.NettyChannelMap,用于进行存放、添加、删除通道等操作。


  NettyChannelMap

四、客户端添加Handler和Bootstrap:

  1.NettyClientHandler,用于进行接收处理服务端消息、断线重连、异常处理等操作。


  NettyClientHandler

  2.NettyClientBootstrap引导程序,用于进行通道创建、通道关闭、通道状态检测等操作。


  NettyClientBootstrap

  至于那个ServerInfoModel无视就好。。。那是我模型层中存取ip用的一个类,各位直接给host附上ip(如:192.168.1.123)即可。

  端口我这里写死为9999。

五、启动服务端和客户端相关程序完成推送。

  1.服务端调用引导程序中的create方法(端口不写9999的话需要把客户端端口改成一致)。

  2.客户端配好正确的ip后调用引导程序中的create方法,用户名和密码按服务端Handler中isLogin方法来即可。

  3.服务端调用引导程序中的pushAll方法,即可完成推送。

  但如果没有现成程序直接移植进去调用的话,可以用我这个JFrame暂时测试一下:


  TestFrame

  以及它的PushServer测试类:


  PushServer

 

最后:

Demo地址:

(注:这个demo是旧的,勉强能用,但上面的那些代码都是最新的,所以大家要用的话可以把上面的那些代码和这个旧demo结合起来进行参考使用。本人略懒就不再整理一份啦,蛤蛤蛤。)