Netty实现时间服务示例

相关知识点:

[1] ChannelGroup是一个容纳打开的通道实例的线程安全的集合,方便我们统一施加操作。所以在使用的过程中可以将一些相关的Channel归类为一个有意义的集合,关闭的通道会自动从集合中移除,而且一个Channel可以属于多个ChannelGroup。常见的应用场景是 向一组通道广播消息;简化一组通道的关闭流程。

[2] 因为在Channel中流通的是ChannelBuffer (可以联系NIO ByteBuffer进行理解),而在内部流水线中处理的可能是一个个对象,所以在收到或要发送到对端的时候就需要一个解码,编码的过程:在实际有意义的对象和字节数组间转换。

[3] 在客户端和服务器端流水线中handler执行顺序是不同的,在客户端中执行顺序和ChannelPipeline的增加顺序一致;而服务器端则恰好是相反的,这一点要注意,所以看到编解码类的位置是那样的。

具体代码:

TimeClient.java

import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;

public class TimeClient {
	public static void main(String[] args) {
		String host = "localhost";
		int port = 8080;

		if(args.length == 2){
			host = args[0];
			port = Integer.parseInt(args[1]);
		}

		ChannelFactory factory = new NioClientSocketChannelFactory(
				Executors.newCachedThreadPool(), Executors.newCachedThreadPool());

		ClientBootstrap bootstrap = new ClientBootstrap(factory);
		bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
			@Override
			public ChannelPipeline getPipeline() throws Exception {
				return Channels.pipeline(new TimeDecoder2(),
										 new TimeClientHandler4());
			}
		});

		ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));  //
		future.awaitUninterruptibly();
		if(!future.isSuccess()){
			future.getCause().printStackTrace();
		}
		future.getChannel().getCloseFuture().awaitUninterruptibly();
		factory.releaseExternalResources();
	}

}

TimeDecoder2.java

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder;

public class TimeDecoder2 extends FrameDecoder{

	@Override
	protected Object decode(ChannelHandlerContext ctx, Channel channel,
			ChannelBuffer buffer) throws Exception {
		if(buffer.readableBytes() < 4)
			return null;
		return new UnixTime(buffer.readInt());
	}
}

TimeClientHandler4.java

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;

public class TimeClientHandler4 extends SimpleChannelHandler{
	@Override
	public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
			throws Exception {
		//the decoder put UnixTime obj,so get just what we need
		UnixTime cur = (UnixTime)e.getMessage();
		System.out.println(cur);
		e.getChannel().close();
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
			throws Exception {
		e.getCause().printStackTrace();
		Channel c = e.getChannel();
		c.close();
	}
}

TimeServer.java

import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.group.ChannelGroupFuture;
import org.jboss.netty.channel.group.DefaultChannelGroup;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;

public class TimeServer {
	//[1]
	public static ChannelGroup allChannels = new DefaultChannelGroup("time-server");

	public static void main(String[] args) {
		ChannelFactory factory = new NioServerSocketChannelFactory(
				Executors.newCachedThreadPool(),
				Executors.newCachedThreadPool());

		ServerBootstrap bootstrap = new ServerBootstrap(factory);
		bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
			@Override
			public ChannelPipeline getPipeline() throws Exception {
				return Channels.pipeline(new TimeServerHandler2(),
										 new TimeEncoder());
			}
		});

		bootstrap.setOption("reuseAddr", true);
		bootstrap.setOption("child.tcpNoDelay", true);
		bootstrap.setOption("child.keepAlive", true);

		Channel channel = bootstrap.bind(new InetSocketAddress(8080));

		allChannels.add(channel);
		//waitForShutdownCommand();  this is a imaginary logic:for instance
		//when there is accepted connection we close this server ;
		if(allChannels.size() >=2){
			ChannelGroupFuture f = allChannels.close();
			f.awaitUninterruptibly();
			factory.releaseExternalResources();
		}
	}
}

TimeServerHandler2.java

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.SimpleChannelHandler;

public class TimeServerHandler2 extends SimpleChannelHandler{
	@Override
	public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e)
			throws Exception {
		TimeServer.allChannels.add(e.getChannel());
	}
	@Override
	public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
			throws Exception {
		UnixTime time = new UnixTime((int) (System.currentTimeMillis() / 1000));
		ChannelFuture f = e.getChannel().write(time);
		f.addListener(ChannelFutureListener.CLOSE);
	}
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
			throws Exception {
		e.getCause().printStackTrace();
		Channel c = e.getChannel();
		c.close();
	}
}

TimeEncoder.java

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;

public class TimeEncoder extends SimpleChannelHandler{
	@Override
	public void writeRequested(ChannelHandlerContext ctx, MessageEvent e)
			throws Exception {
		UnixTime time = (UnixTime)e.getMessage();
		ChannelBuffer buf = ChannelBuffers.buffer(4);
		buf.writeInt(time.getValue());
		Channels.write(ctx, e.getFuture(), buf);
	}
}

UnixTime.java

import java.util.Date;

public class UnixTime {
	private int value;
	public UnixTime(int value){
		this.value = value;
	}
	public int getValue(){
		return this.value;
	}
	public void setValue(int value){
		this.value = value;
	}
	@Override
	public String toString() {
		//Allocates a Date object and initializes it to represent the specified number
		//of milliseconds since the standard base time known as "the epoch",
		//namely January 1, 1970, 00:00:00 GMT
		return new Date(value * 1000L).toString();
	}
}

Netty实现时间服务示例

时间: 2024-10-13 02:23:26

Netty实现时间服务示例的相关文章

Netty学习之服务器端创建

一.服务器端开发时序图 图片来源:Netty权威指南(第2版) 二.Netty服务器端开发步骤 使用Netty进行服务器端开发主要有以下几个步骤: 1.创建ServerBootstrap实例 ServerBootstrap b=new ServerBootstrap(); ServerBootstrap是Netty服务器端的启动辅助类,提供了一系列的方法用于设置服务器端启动相关的参数. 2.设置并绑定Reactor线程池 EventLoopGroup bossGruop=new NioEvent

BIO、NIO、AIO系列二:Netty

一.概述 Netty是一个Java的开源框架.提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序. Netty是一个NIO客户端,服务端框架.允许快速简单的开发网络应用程序.例如:服务端和客户端之间的协议,它简化了网络编程规范. 二.NIO开发的问题 1.NIO类库和API复杂,使用麻烦. 2.需要具备Java多线程编程能力(涉及到Reactor模式). 3.客户端断线重连.网络不稳定.半包读写.失败缓存.网络阻塞和异常码流等问题处理难度非常大 4

netty 之 telnet HelloWorld 详解

依赖工具 Maven Git JDK IntelliJ IDEA 源码拉取 从官方仓库 https://github.com/netty/netty Fork 出属于自己的仓库.为什么要 Fork ?既然开始阅读.调试源码,我们可能会写一些注释,有了自己的仓库,可以进行自由的提交.?? 使用 IntelliJ IDEA 从 Fork 出来的仓库拉取代码. 本文使用的 Netty 版本为 4.1.26.Final-SNAPSHOT . Maven Profile 打开 IDEA 的 Maven P

Netty 实现心跳机制.md

netty 心跳机制示例,使用netty4,IdleStateHandler 实现. 本文假设你已经了解了Netty的使用,或者至少写过netty的helloworld,知道了netty的基本使用.我们知道使用netty的时候,大多数的东西都与Handler有关,我们的业务逻辑基本都是在Handler中实现的.Netty中自带了一个IdleStateHandler 可以用来实现心跳检测. 心跳检测的逻辑 本文中我们将要实现的心跳检测逻辑是这样的:服务端启动后,等待客户端连接,客户端连接之后,向服

Spring Cloud Gateway - 扩展

[TOC] Spring Cloud Gateway的监控端点 说到监控,就应该能想到Spring Boot Actuator.而Spring Cloud Gateway基于Actuator提供了许多的监控端点.只需要在项目中添加spring-boot-starter-actuator依赖,并将 gateway 端点暴露,即可获得若干监控端点.配置示例: management: endpoints: web: exposure: include: gateway # 或者配置"*"暴露

Netty 入门示例

服务端代码示例 import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; public class TimeServer { public void bind(int port) throws Except

Netty中分隔符解码器代码示例与分析

[toc] Netty中分隔符解码器代码示例与分析 通过特别解码器的使用,可以解决Netty中TCP的粘包问题,上一篇<Netty中LineBasedFrameDecoder解码器使用与分析:解决TCP粘包问题>通过行解码器的使用来解决TCP粘包问题,这意味着Netty的服务端和客户端在每次发送请求消息前,都需要在消息的尾部拼接换行符. 除了使用行解码器外,Netty还提供了通用的分隔符解码器,即可以自定义消息的分隔符,那就是DelimiterBasedFrameDecoder分隔符解码器.

netty 对象序列化传输示例

package object.server.impl; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.nio.NioEventLoopGroup; import io.

分别使用Java IO、NIO、Netty实现的一个Echo Server示例

分别使用Java IO.Java NIO.Netty来实现一个简单的EchoServer(即原样返回客户端的输入信息). Java IO int port = 9000; ServerSocket ss = new ServerSocket(port); while (true) { final Socket socket = ss.accept(); new Thread(new Runnable() { public void run() { while (true) { try { Buf