原文出自:http://blog.csdn.net/anxpp/article/details/52139155,转载请注明出处,想想!
1、概述
Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。
目前最新的是版本是4.1.4(5.x版本官网已经弃用,不推荐使用)。
Netty4.x同时也是原生支持Android的,所以后面的程序,放到android上也是可以正常运行的(亲测)。
项目如果使用Maven开发,直接添加以下依赖即可:
2、实现服务端
首先是消息处理类ServerHandler:
- package com.anxpp.im.server.handler;
- import io.netty.channel.ChannelHandler;
- import io.netty.channel.ChannelHandlerContext;
- import io.netty.channel.ChannelInboundHandlerAdapter;
- import java.io.IOException;
- import com.anxpp.im.common.IMMessage;
- import com.anxpp.im.common.OnlineUser;
- import com.anxpp.im.server.config.BaseConfig;
- @ChannelHandler.Sharable
- public class ServerHandler extends ChannelInboundHandlerAdapter implements BaseConfig{
- private ChannelHandlerContext ctx;
- @Override
- public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
- System.err.println("服务端Handler创建...");
- super.handlerAdded(ctx);
- }
- @Override
- public void channelInactive(ChannelHandlerContext ctx) throws Exception {
- System.err.println("channelInactive");
- super.channelInactive(ctx);
- }
- /**
- * tcp链路建立成功后调用
- */
- @Override
- public void channelActive(ChannelHandlerContext ctx) throws Exception {
- this.ctx = ctx;
- System.err.println("有客户端连接:"+ctx.channel().remoteAddress().toString());
- }
- /**
- * 发送消息
- */
- public boolean sendMsg(IMMessage msg) throws IOException {
- System.err.println("服务器推送消息:"+msg);
- ctx.writeAndFlush(msg);
- return msg.getMsg().equals("q") ? false : true;
- }
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) throws IOException {
- System.err.println("服务器接收到消息:"+msg);
- IMMessage message = (IMMessage)msg;
- if(OnlineUser.get(message.getReceiveId())==null){
- OnlineUser.put(message.getUid(), ctx);
- }
- ChannelHandlerContext c = OnlineUser.get(message.getReceiveId());
- if(c==null){
- message.setMsg("对方不在线!");
- OnlineUser.get(message.getUid()).writeAndFlush(message);
- }
- else
- c.writeAndFlush(message);
- }
- /**
- * 异常处理
- */
- @Override
- public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
- System.err.println("与客户端断开连接:"+cause.getMessage());
- cause.printStackTrace();
- ctx.close();
- }
- }
接收客户端连接,如果客户端没有连接过,就保存ChannelHandlerContext到Map中用于发送消息。然后判断消息接收方是否在线,若在线就直接发送消息,没有在线就返回“对方不在线”。当然,可以将消息发送者和消息接收者ID设置为相同就能仅开一个客户端自己跟自己聊天(类似Echo Server)。
服务器程序Server:
- package com.anxpp.im.server;
- import io.netty.bootstrap.ServerBootstrap;
- import io.netty.channel.ChannelFuture;
- import io.netty.channel.ChannelInitializer;
- import io.netty.channel.ChannelOption;
- import io.netty.channel.EventLoopGroup;
- import io.netty.channel.nio.NioEventLoopGroup;
- import io.netty.channel.socket.SocketChannel;
- import io.netty.channel.socket.nio.NioServerSocketChannel;
- import io.netty.handler.codec.LengthFieldBasedFrameDecoder;