文章目录
1、netty4.x
2、netty实例
正文部分
1、netty4.x
原文:
The minimum requirements to run the examples which are introduced in this chapter are only two;
the latest version of Netty and JDK 1.6 or above.
The latest version of Netty is available in the project download page.
To download the right version of JDK, please refer to your preferred JDK vendor's web site.
要点:
a.演示例子里边使用的是netty4.x最新版本的架包。
b.JDK1.6或者1.6以上版本。
下载地址:
http://netty.io/Main/Downloads
http://www.oracle.com/technetwork/java/javase/downloads/index.html
2、netty实例
2.1、Writing a Discard Server 抛弃协议
原文:
http://tools.ietf.org/html/rfc863 Discard Protocol协议
A useful debugging and measurement tool is a discard service. A discard service simply throws away any data it receives.
要点:
a.接收到什么抛弃什么,它对调试网络状态有一定的用处。
b.服务器就会在TCP端口9检测抛弃协议请求,在建立连接后并检测到请求后,就直接把接收到的数据直接抛弃,直到用户中断连接。
c.UDP协议类似TCP的方式,端口也是9。
代码如下:
DiscardServerHandler 业务处理handler类
代码要点:
a.handler继承ChannelInboundByteHandlerAdapter方式来实现,实在要实现handler接口实现也是OK的。
b.覆写inboundBufferUpdated方法,ByteBuf携带从client发送过来的数据,调用基于抛弃协议实现的clear方法。
c.exceptionCaught方法在出现异常时候执行,比如可以发送一条错误消息到client端。
1 package io.netty.example.discard; 2
3 import io.netty.buffer.ByteBuf; 4 import io.netty.channel.ChannelHandlerContext; 5 import io.netty.channel.ChannelInboundByteHandlerAdapter; 6
7 import java.util.logging.Level; 8 import java.util.logging.Logger; 9
10 /**
11 * Handles a server-side channel. 12 */
13 public class DiscardServerHandler extends ChannelInboundByteHandlerAdapter { 14
15 private static final Logger logger = Logger.getLogger( 16 DiscardServerHandler.class.getName()); 17
18 @Override 19 public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception { 20 // Use direct buffer if possible. 21 // If you are going to use a heap buffer, you don't need to override this method.
22 return ctx.alloc().ioBuffer(); 23 } 24
25 @Override 26 public void inboundBufferUpdated(ChannelHandlerContext ctx, ByteBuf in) 27 throws Exception { 28 while(in.readable()){ 29 System.out.println((char)in.readByte()); // 将内容打印出来,方便调式而已
30 System.out.flush(); 31 } 32 // Discard the received data silently.
33 in.clear(); 34 } 35
36 @Override 37 public void exceptionCaught(ChannelHandlerContext ctx, 38 Throwable cause) throws Exception { 39 // Close the connection when an exception is raised.
40 logger.log( 41 Level.WARNING, 42 "Unexpected exception from downstream.", 43 cause); 44 ctx.close(); 45 } 46 }
代码如下:
DiscardServer 抛弃协议服务器端代码
要点:
netty4.x比起netty3.x做了一些变化
1 package io.netty.example.discard; 2
3 import io.netty.bootstrap.ServerBootstrap; 4 import io.netty.channel.ChannelFuture; 5 import io.netty.channel.ChannelInitializer; 6 import io.netty.channel.socket.SocketChannel; 7 import io.netty.channel.nio.NioEventLoopGroup; 8 import io.netty.channel.socket.nio.NioServerSocketChannel; 9
10 /**
11 * Discards any incoming data. 12 */
13 public class DiscardServer { 14
15 private final int port; // 服务器绑定的tcp端口号
16
17 public DiscardServer(int port) { 18 this.port = port; 19 } 20
21 public void run() throws Exception { 22 ServerBootstrap b = new ServerBootstrap(); // netty server端启动类
23 try { 24 // netty4.x和3.x的变化地方,提供各种EventLoopGroup实现类来支持各种传输协议。
25 b.group(new NioEventLoopGroup(), new NioEventLoopGroup()) // 第一个loop负责接收request,第二个负责处理perform。
26 .channel(NioServerSocketChannel.class) 27 .childHandler(new ChannelInitializer<SocketChannel>() { 28 @Override 29 public void initChannel(SocketChannel ch) throws Exception { 30 ch.pipeline().addLast(new DiscardServerHandler()); // server和client创建成功一个connection后会call这个方法。
31 } 32 }); 33
34 // server绑定在某个端口,等待client的连接
35 ChannelFuture f = b.bind(port).sync(); 36
37 // Wait until the server socket is closed. 38 // In this example, this does not happen, but you can do that to gracefully 39 // shut down your server.
40 f.channel().closeFuture().sync(); 41 } finally { 42 b.shutdown(); 43 } 44 } 45
46 public static void main(String[] args) throws Exception { 47 int port; 48 if (args.length > 0) { 49 port = Integer.parseInt(args[0]); 50 } else { 51 port = 8080; 52 } 53 new DiscardServer(port).run(); 54 } 55 }
通过telnet localhost 8080来测试下代码运行性,server端代码稍等改下。
其他client端口见netty包里提供的例子代码。
2.2、Writing an Echo Server 应答协议
原文:
Echo Protocol https://tools.ietf.org/html/rfc862
A very useful debugging and measurement tool is an echo service. An echo service simply sends back to the originating source any data it receives.
要点:
a.类似抛弃协议应答协议也是一个调式的工具服务协议。
b.echo服务协议是将接收到的内容返回给发送方。
c.基于TCP/UDP协议都有实现,同在端口7中监听。
代码如下:
EchoServerHandler 服务器端业务处理handler类
1 package io.netty.example.echo; 2
3 import io.netty.buffer.ByteBuf; 4 import io.netty.channel.ChannelHandler.Sharable; 5 import io.netty.channel.ChannelHandlerContext; 6 import io.netty.channel.ChannelInboundByteHandlerAdapter; 7
8 import java.util.logging.Level; 9 import java.util.logging.Logger; 10
11 /**
12 * Handler implementation for the echo server. 13 */
14 @Sharable 15 public class EchoServerHandler extends ChannelInboundByteHandlerAdapter { 16
17 private static final Logger logger = Logger.getLogger( 18 EchoServerHandler.class.getName()); 19
20 @Override 21 public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception { 22 // Use direct buffer if possible. 23 // If you are going to use a heap buffer, you don't need to override this method.
24 return ctx.alloc().ioBuffer(); 25 } 26
27 @Override 28 public void inboundBufferUpdated(ChannelHandlerContext ctx, ByteBuf in) { 29 ByteBuf out = ctx.nextOutboundByteBuffer(); // 从ctx中获取outbound发包buffer
30 out.writeBytes(in); // 将server端接收到的内容又写回到client端去 31 // notify that there is some data to flush out (send) to the remote peer.
32 ctx.flush(); // 触发send content操作
33 } 34
35 @Override 36 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 37 // Close the connection when an exception is raised.
38 logger.log(Level.WARNING, "Unexpected exception from downstream.", cause); 39 ctx.close(); 40 } 41 }
server端代码如下:
1 package io.netty.example.echo; 2
3 import io.netty.bootstrap.ServerBootstrap; 4 import io.netty.channel.ChannelFuture; 5 import io.netty.channel.ChannelInitializer; 6 import io.netty.channel.ChannelOption; 7 import io.netty.channel.socket.SocketChannel; 8 import io.netty.channel.nio.NioEventLoopGroup; 9 import io.netty.channel.socket.nio.NioServerSocketChannel; 10 import io.netty.handler.logging.LogLevel; 11 import io.netty.handler.logging.LoggingHandler; 12
13 /**
14 * Echoes back any received data from a client. 15 */
16 public class EchoServer { 17
18 private final int port; 19
20 public EchoServer(int port) { 21 this.port = port; 22 } 23
24 public void run() throws Exception { 25 // Configure the server.
26 ServerBootstrap b = new ServerBootstrap(); 27 try { 28 b.group(new NioEventLoopGroup(), new NioEventLoopGroup()) 29 .channel(NioServerSocketChannel.class) 30 .option(ChannelOption.SO_BACKLOG, 100) 31 .handler(new LoggingHandler(LogLevel.INFO)) 32 .childHandler(new ChannelInitializer<SocketChannel>() { 33 @Override 34 public void initChannel(SocketChannel ch) throws Exception { 35 ch.pipeline().addLast( 36 new LoggingHandler(LogLevel.INFO), 37 new EchoServerHandler()); 38 } 39 }); 40
41 // Start the server.
42 ChannelFuture f = b.bind(port).sync(); 43
44 // Wait until the server socket is closed.
45 f.channel().closeFuture().sync(); 46 } finally { 47 // Shut down all event loops to terminate all threads.
48 b.shutdown(); 49 } 50 } 51
52 public static void main(String[] args) throws Exception { 53 int port; 54 if (args.length > 0) { 55 port = Integer.parseInt(args[0]); 56 } else { 57 port = 8080; 58 } 59 new EchoServer(port).run(); 60 } 61 }
client端代码类似抛弃协议中的client,具体查看源代码即可。
2.3、Writing a Time Server 时间同步协议
原文:
This protocol provides a site-independent, machine readable date and time.
The Time service sends back to the originating source the time in seconds since midnight on January first 1900.
要点:
a.client端和server端time同步协议。
b.基于TCP,UDP都有相应的实现。
TCP实现如下:
=============================
S:服务器在37端口监听。
U:用户connect连接到37端口。
S:发送32位数字。
U:接收数字time。
S:关闭connection。
U:关闭连接。
UDP时间见链接:http://tools.ietf.org/html/rfc868
新版本包里居然没有time的演示代码,有点奇怪。待定。