demo1
简单的一个服务器实现,访问该服务器,返回一个"hello netty" 到网页
1.启动类
public class HelloServer {
public static void main(String[] args) throws Exception{
EventLoopGroup boosGroup=new NioEventLoopGroup();
EventLoopGroup workerGroup =new NioEventLoopGroup();
try{
ServerBootstrap bootstrap=new ServerBootstrap();
bootstrap.group(boosGroup,workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new HelloServerInitializer());
ChannelFuture channelFuture=bootstrap.bind(8088).sync();
channelFuture.channel().closeFuture().sync();
}finally {
boosGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
初始化
public class HelloServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
//通过SockerChannel 去获得对应的管道
ChannelPipeline pipeline= socketChannel.pipeline();
pipeline.addLast("HttpServerCodec",new HttpServerCodec());
pipeline.addLast("customHandler",new CustomerHandler());
}
}
处理类
public class CustomerHandler extends SimpleChannelInboundHandler<HttpObject> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
Channel channel=ctx.channel();
if(msg instanceof HttpRequest){
System.out.println(channel.remoteAddress());
ByteBuf content=Unpooled.copiedBuffer("hello ",CharsetUtil.UTF_8);
FullHttpResponse response=new DefaultFullHttpResponse(HttpVersion.HTTP_1_0,
HttpResponseStatus.OK,content);
response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain");
response.headers().set(HttpHeaderNames.CONTENT_LENGTH,content.readableBytes());
ctx.writeAndFlush(response);
}
}
}
demo2
使用netty实现简单的聊天长连接(websocket)
启动类
public class WSServer {
public static void main(String[] args) throws Exception {
//先写两个主从线程组
EventLoopGroup MainGroup=new NioEventLoopGroup();
EventLoopGroup subGroup=new NioEventLoopGroup();
try {
//启动类
ServerBootstrap bootstrap = new ServerBootstrap();
//绑定
bootstrap.group(MainGroup,subGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new WSServerInitialzer());
//开启启动接口
ChannelFuture channelFuture=bootstrap.bind(8088).sync();
channelFuture.channel().closeFuture().sync();
//关闭
}finally {
MainGroup.shutdownGracefully();
subGroup.shutdownGracefully();
}
}
}
初始化
public class WSServerInitialzer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
//获得管道
ChannelPipeline channelPipeline=socketChannel.pipeline();
//对管道进行handler绑定,类似拦截器链
//1.基于http协议的 解码器
channelPipeline.addLast(new HttpServerCodec());
//2.对大数据流的支持
channelPipeline.addLast(new ChunkedWriteHandler());
//3.对httpMessage的聚合(都会使用的)
channelPipeline.addLast(new HttpObjectAggregator(1024*64));
//httpWebSocket支持,长连接
channelPipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
channelPipeline.addLast(new ChatHandler());
}
}
处理类
public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
//客户端
private static ChannelGroup clients=new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
//获取传过来的消息
String content=msg.text();
System.out.println("接收到:"+content);
//返回客户端消息
clients.writeAndFlush(new TextWebSocketFrame("[服务器在]"+ LocalDateTime.now()+"接受到消息,消息为:"+content));
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
clients.add(ctx.channel());
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
System.out.println("客户但断开,channle对应的长id为:"+ctx.channel().id().asLongText());
System.out.println("客户端断开,channel对应的短id为:"+ctx.channel().id().asShortText());
}
}
demo3
官方写法
public class NettyDiscardServer {
private int serverPort=8080;
ServerBootstrap b=new ServerBootstrap();
public NettyDiscardServer(int port){
this.serverPort=port;
}
public void runServer(){
//创建反应器线程组
EventLoopGroup bossLoopGroup=new NioEventLoopGroup(1);
EventLoopGroup workerLoopGroup=new NioEventLoopGroup();
try{
//1 设置反应器线程组
b.group(bossLoopGroup,workerLoopGroup);
//2 设置nio类型的通道
b.channel(NioServerSocketChannel.class);
//3 设置监听端口
b.localAddress(serverPort);
//4 设置通道的参数
b.option(ChannelOption.SO_KEEPALIVE,true);
b.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
//5 装配子通道流水线
b.childHandler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel ch){
ch.pipeline().addLast(new NettyDiscardHandler());
}
});
//6 开始绑定服务器,通过调用sync同步方法阻塞直到绑定成功
ChannelFuture channelFuture=b.bind().sync();
//7 等待通道关闭的异步任务结束
ChannelFuture closeFuture =channelFuture.channel().closeFuture();
closeFuture.sync();
//8 关闭EventLoopGroup
workerLoopGroup.shutdownGracefully();
bossLoopGroup.shutdownGracefully();
}catch (Exception e){
e.printStackTrace();
}
}
}
业务处理器:NettyDiscardHandler
public class NettyDiscardHandler extends ChannelInboundHandlerAdapter {
public void channelRead(ChannelHandlerContext ctx,Object msg)throws Exception{
ByteBuf in=(ByteBuf) msg;
while(in.isReadable())
System.out.print((char)in.readByte());
}
}
Reactor反应器作用:进行一个IO事件的select查询和dispatch分发(调用对应的handler)。
应用场景不同,用到的反应器也不相同,对于NIO通信,对于的反应器类型:NioEventLoopGroup
上面使用了两个反应器,一个是负责IO事件的监听,一个是负责传输通道的IO事件的处理。
ServerBootstrap是一个服务启动类,它的职责就是组装集成器,将不同的Netty组件组装起来。
这里产生一个新的概念:入站和出战;简单的来说,入站就是输入的意思,出战就是输出的意思。