目录
netty简介
Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,
用以快速开发高性能、高可靠性的网络服务器和客户端程序。
也就是说,Netty 是一个基于NIO的客户、服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,
例如实现了某种协议的客户、服务端应用。Netty相当于简化和流线化了网络应用的编程开发过程,例如:基于TCP和UDP的socket服务开发。
“快速”和“简单”并不用产生维护性或性能上的问题。
Netty 是一个吸收了多种协议(包括FTP、SMTP、HTTP等各种二进制文本协议)的实现经验,
并经过相当精心设计的项目。最终,Netty 成功的找到了一种方式,在保证易于开发的同时还保证了其应用的性能,稳定性和伸缩性。
以上摘自百度百科
下载netty的jar包 下载地址 http://netty.io/downloads.html
下载 netty-4.1.27.Final 版本
官网上面已经说明了,jdk的版本需要1.6 以上
下载后解压,内容如下
示例1 discard
基于TCP的丢弃服务
一个丢弃服务被定义为基于连接的应用程序
TCP。服务器侦听TCP端口9上的TCP连接
建立连接任何收到的数据都会被丢弃。没有
响应已发送。这一直持续到主叫用户终止
连接。
基于UDP的丢弃服务
另一个丢弃服务被定义为基于数据报的应用程序
UDP。服务器在UDP端口9上侦听UDP数据报
收到数据报后,它就被丢弃了。没有回复。
netty 官方给出了一个示例,告诉你世界上最简单的协议不是"hello world " ,而是DISCARD(抛弃服务),这个协议将会抛弃任何收到的协议而不响应
package com.shj.netty;
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;
/** netty服务端
* @Description
* @Author shj
* @Date 17:57 2018/7/19
* @Param
* @return
**/
public class NettyServer {
private static final int PORT=888;
public static void main(String[] args) {
/**
NioEventLoopGroup 是用来处理I/O操作的多线程事件循环器,Netty 提供了许多不同的
EventLoopGroup 的实现用来处理不同的传输。在这个例子中我们实现了一个服务端的应用,
因此会有2个 NioEventLoopGroup 会被使用。第一个经常被叫做‘boss’,用来接收进来的连
接。第二个经常被叫做‘worker’,用来处理已经被接收的连接,一旦‘boss’接收到连接,就会
把连接信息注册到‘worker’上。如何知道多少个线程已经被使用,如何映射到已经创建的
Channel上都需要依赖于 EventLoopGroup 的实现,并且可以通过构造函数来配置他们的关
系
*/
EventLoopGroup bossGroup=new NioEventLoopGroup();
EventLoopGroup workerGroup=new NioEventLoopGroup();
try {
/** ServerBootstrap 是一个启动 NIO 服务的辅助启动类。你可以在这个服务中直接使用
Channel,但是这会是一个复杂的处理过程,在很多情况下你并不需要这样做
*/
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup,workerGroup)
/**
* 这里我们指定使用 NioServerSocketChannel 类来举例说明一个新的 Channel 如何接收进来
的连接
**/
.channel(NioServerSocketChannel.class)
/**
* 这里的事件处理类经常会被用来处理一个最近的已经接收的 Channel。ChannelInitializer 是
一个特殊的处理类,他的目的是帮助使用者配置一个新的 Channel。也许你想通过增加一些
处理类比如NettyServerHandler 来配置一个新的 Channel 或者其对应的ChannelPipeline
来实现你的网络程序。当你的程序变的复杂时,可能你会增加更多的处理类到 pipline 上,然
后提取这些匿名类到最顶层的类上
**/
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new NettyServerHandler());
}
})
/**
*
*你可以设置这里指定的 Channel 实现的配置参数。我们正在写一个TCP/IP 的服务端,因此
我们被允许设置 socket 的参数选项比如tcpNoDelay 和 keepAlive
**/
.option(ChannelOption.SO_BACKLOG,128)
/**
option() 是提供给NioServerSocketChannel 用来接
收进来的连接。childOption() 是提供给由父管道 ServerChannel 接收到的连接,在这个例子
中也是 NioServerSocketChannel。
**/
.childOption(ChannelOption.SO_KEEPALIVE,true);
// 绑定端口,开始接受进来的连接
ChannelFuture channelFuture =serverBootstrap.bind(PORT).sync();
// 等待服务器 socket关闭
channelFuture.channel().closeFuture().sync();
}catch (Exception e){
e.printStackTrace();
}finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
}
此时启动程序,然后在控制台输入 telnet 127.0.0.1 888
如果出现弹出窗口,则说明此服务器启动成功
为了更好的测试效果,修改服务端处理数据的方式,将收到的信息打印出来
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf byteBuf= (ByteBuf) msg;
try{
while (byteBuf.isReadable()){
System.out.print( (char) byteBuf.readByte());
System.out.flush();
}
}finally{
ReferenceCountUtil.release(msg);
}
}
然后就可以将客户端发送的信息在控制台打印出来
实例2 echo 服务器
基于TCP的回声服务
一个echo服务被定义为TCP上基于连接的应用程序。
服务器侦听TCP端口7上的TCP连接
建立连接任何收到的数据都会被发回。这个
继续,直到主叫用户终止连接。
基于UDP的回声服务
另一个echo服务被定义为基于数据报的应用程序
UDP。服务器在UDP端口7上侦听UDP数据报
接收到数据报,来自它的数据在回答中被发回
数据报。
和 Discard 的区别就在于修改对数据的处理方式
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
/**
* ChannelHandlerContext 对象提供了许多操作,使你能够触发各种各样的 I/O 事件和操
作。这里我们调用了 write(Object) 方法来逐字地把接受到的消息写入。请注意不同于
DISCARD 的例子我们并没有释放接受到的消息,这是因为当写入的时候 Netty 已经帮我
们释放了。
**/ ctx.write(msg);
/** ctx.write(Object) 方法不会使消息写入到通道上,他被缓冲在了内部,你需要调用
ctx.flush() 方法来把缓冲区中数据强行输出。或者你可以用更简洁的
cxt.writeAndFlush(msg) 以达到同样的目的。*/
ctx.flush();
}