一个简单的Netty服务器
编程语言
2018-12-20 17:14:47
阅读次数: 0
大纲
- 构建一对主从线程组
- 定义服务器启动类
- 为服务器设置Channel
- 设置处理从线程池的助手类初始化器
- 监听启动和关闭服务器
步骤
- 新建Maven空项目,pom.xml添加Netty依赖;
<dependencies>
<!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.25.Final</version>
</dependency>
</dependencies>
- 建立启动类HelloServer.java;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
/**
* @Description: 服务器启动类,实现客户端发送一个请求,服务器会返回 hello netty
*/
public class HelloServer {
public static void main(String[] args) throws Exception {
//定义两个线程池(线程组)
//主线程组,用于接受客户端的连接,不做任何处理
EventLoopGroup bossGroup =new NioEventLoopGroup() ;
//从线程组,接受主线程组抛出的任务
EventLoopGroup wokerGroup =new NioEventLoopGroup() ;
try {
//netty服务器的创建,ServerBootstrap是一个启动类
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup,wokerGroup) //设置主从线程组
.channel(NioServerSocketChannel.class) //设置nio双向通道
.childHandler(null); //子处理器,用于处理wokerGroup
//用于启动server,并且设置端口,设置启动方式为同步
ChannelFuture channelFuture = serverBootstrap.bind(8088).sync();
//监听关闭channel,设置为同步方式
channelFuture.channel().closeFuture().sync();
} finally {
//优雅关闭
bossGroup.shutdownGracefully();
wokerGroup.shutdownGracefully();
}
}
}
- 设置子处理器Channel(初始化器);
- 建立一个初始化器HelloServerInitializer.java ;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;
/**
* @Description: 这是一个初始化器,当channle注册后,会执行里面相应的初始化方法
*/
public class HelloServerInitializer extends ChannelInitializer<SocketChannel> {
protected void initChannel(SocketChannel channel) throws Exception {
//通过channel获取对应的管道pipeline
ChannelPipeline pipeline = channel.pipeline();
//通过管道pipeline添加handler
pipeline.addLast("HttpServerCodec",new HttpServerCodec()) //HttpServerCodec是Netty自己提供的助手类,请求到服务端时解码,响应到客户端时编码
.addLast("customHandler",null) //添加自定义的助手类 功能待添加
;
}
}
- 修改启动类HelloServer.java,将子处理器声明为刚刚建立的初始化器;
serverBootstrap.group(bossGroup,wokerGroup) //设置主从线程组
.channel(NioServerSocketChannel.class) //设置nio双向通道
.childHandler(new HelloServerInitializer()); //子处理器,用于处理wokerGroup,功能在初始化器中定义
- 创建自定义的助手类CustomHandler.java;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;
/**
* @Description: 自定义助手类
*/
//SimpleChannelInboundHandler:对于请求来讲,相当于入站
public class CustomHandler extends SimpleChannelInboundHandler<HttpObject> {
protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
//获取Channel
Channel channel = ctx.channel();
if (msg instanceof HttpRequest) {
//显示客户端你的远程地址
System.out.println(channel.remoteAddress());
//定义发送的数据消息
ByteBuf content = Unpooled.copiedBuffer("Hello Netty!", CharsetUtil.UTF_8);
//构建一个HttpResponse 1.1版本会默认开启一个长连接,效率会高过1.0
DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);
//为响应增加数据类型和长度
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());
//把响应返回(刷)给客户端,先写后刷
ctx.writeAndFlush(response);
}
}
}
- 将自定义的助手类声明到初始化类,修改HelloServerInitializer.java
//通过管道pipeline添加handler
pipeline.addLast("HttpServerCodec",new HttpServerCodec()) //HttpServerCodec是Netty自己提供的助手类,请求到服务端时解码,响应到客户端时编码
.addLast("customHandler",new CustomHandler()) //添加自定义的助手类
;
- 至此自定义助手类已经配置完毕;
- 启动HelloServer.java,运行main 方法开启Netty服务;
- 浏览器测试:http://localhost:8088/
- 测试结果:
- 完毕
转载自blog.csdn.net/xlikec/article/details/85112255