根据Netty框架实现消息推送(即时聊天)功能.
Netty框架,TCP长连接,心跳,阻塞消息队列,线程池处理消息发送, 基于Google ProtoBuf自定义的消息协议, TCP粘包/拆包....
客户端通过TCP连接到服务器,并建立TCP长连接;当服务器端收到新消息后通过TCP连接推送给客户端, 即消息传递方式: 客户端A -> 服务器 -> 客户端B.
不说了,直接上核心代码吧:
================ Server端核心代码 ===========================
//服务端主类.
public final class NettyServer {
public static int PORT = 10000;
public final int HEART_SYNC_TIME = 300;
private EventLoopGroup bossGroup;
private EventLoopGroup workerGroup;
public void bind(int port) throws InterruptedException{
bossGroup = new NioEventLoopGroup(1);
workerGroup = new NioEventLoopGroup();
ServerBootstrap bootstrap=new ServerBootstrap();
try {
bootstrap.group(bossGroup, workerGroup);
bootstrap.channel(NioServerSocketChannel.class);
bootstrap.option(ChannelOption.SO_BACKLOG, 1024);
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 pipe = socketChannel.pipeline();
pipe.addLast( new ProtobufVarint32FrameDecoder());
pipe.addLast(new ProtobufDecoder(MessageProto.Message .getDefaultInstance()));
pipe.addLast(new ProtobufVarint32LengthFieldPrepender());
pipe.addLast(new ProtobufEncoder());
pipe.addLast(new MessageServerHandler());
}
});
// Bind and start to accept incoming connections.
ChannelFuture f = bootstrap.bind(port).sync();
if(f.isSuccess()){
Log.debug("server start success... port: " + port + ", main work thread: " + Thread.currentThread().getId());
}
// Wait until the server socket is closed.
f.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
public synchronized void stop(){
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
public static void main(String []args) {
NettyServer server = null;
try {
server = new NettyServer();
if(args != null && args.length>0 && args[0].length() > 3){
PORT = Integer.parseInt(args[0]);
}
//message work thread.
new Thread(new Runnable(){
@Override
public void run() {
MessageManager.getInstance().start();
}
}).start();
server.bind(PORT);
} catch (InterruptedException e) {
MessageManager.getInstance().stop();
UserManager.getInstance().clearAll();
server.stop();
e.printStackTrace();
}
}
}
//消息分发
public class MessageManager {
private static MessageManager manager;
private LinkedBlockingQueue<Message> mMessageQueue = new LinkedBlockingQueue<Message>();
private ThreadPoolExecutor mPoolExecutor = new ThreadPoolExecutor(5, 10, 15, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new ThreadPoolExecutor.AbortPolicy());
private MessageManager(){
}
public static MessageManager getInstance(){
if(manager == null){
synchronized (MessageManager.class) {
if(manager == null){
manager = new MessageManager();
}
}
}
return manager;
}
public void putMessage(Message message){
Log.debug("MessageManager-> putMessage(