强烈推荐去弄懂Netty流程,再来写这个代码:
/**
* 实现客户端发送一个请求,服务器返回信息
* [主从线程模型]
*/
public class HelloServer {
public static void main(String[] args) throws InterruptedException {
// 主线程组 [接受客户端连接,但不做处理,和老板一样] 这个是主从模式的
EventLoopGroup bosGroup = new NioEventLoopGroup();
//从线程组 【老板线程组把任务丢给他,让手下去做任务 中介....】
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
// netty服务器的创建, ServerBootstrap 是一个启动类
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bosGroup, workerGroup) // 设置主从线程组
.channel(NioServerSocketChannel.class) // 设置nio的双向通道
.childHandler(new HelloServerInitializer()); // 子处理器,用于处理workerGroup
// 启动server,并且设置8088为启动的端口号,同时启动方式为同步
ChannelFuture channelFuture = serverBootstrap.bind(8088).sync();
// 监听关闭的channel,设置为同步方式
channelFuture.channel().closeFuture().sync();
} finally {
bosGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
HelloServer
/**
* 初始化器 channel注册后 会执行里面相对应的初始化方法
*/
public class HelloServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
//通过SocketChannel去获得对应的管道
ChannelPipeline pipeline = socketChannel.pipeline();
// 当请求到服务端,我们需要做解码,响应到客户端做编码
pipeline.addLast("HttpServerCodec",new HttpServerCodec());
// 添加自定义的助手类,返回 "hello netty"
pipeline.addLast("customHandler",new CustomHandler());
}
}
HelloServerInitializer
/**
* @Description: 创建自定义助手类
*/
//SimpleChannelInboundHandler: 对于请求来讲,其实相当于[入站,入境]
public class CustomHandler extends SimpleChannelInboundHandler<HttpObject> {
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, HttpObject httpObject) throws Exception {
// 通过上下文对象获取channel
Channel channel = channelHandlerContext.channel();
//判断请求是否Request请求
if (httpObject instanceof HttpRequest){
// 显示客户端的远程地址
System.out.println(channel.remoteAddress());
// 定义发送的数据消息
ByteBuf content = Unpooled.copiedBuffer("Hello,Netty!", CharsetUtil.UTF_8);
//构建一个http response
DefaultFullHttpResponse response =
new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
HttpResponseStatus.OK,
content);
// 为响应增加数据类型和长度(content.readableBytes是算出长度)
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());
// 把响应刷到客户端 [写 和 刷新]
channelHandlerContext.writeAndFlush(response);
}
}
// 下面是Channel的一下生命周期,我们重写即可
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
System.out.println("Channel---注册");
super.channelRegistered(ctx);
}
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
System.out.println("Channel---移除");
super.channelUnregistered(ctx);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("Channel---活跃状态");
super.channelActive(ctx);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
System.out.println("Channel---不活跃了");
super.channelInactive(ctx);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
System.out.println("Channel---读取完毕");
super.channelReadComplete(ctx);
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
System.out.println("Channel---用户事件触发");
super.userEventTriggered(ctx, evt);
}
@Override
public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
System.out.println("Channel---可写可改");
super.channelWritabilityChanged(ctx);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.out.println("Channel---捕获异常触发函数");
super.exceptionCaught(ctx, cause);
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
System.out.println("Channel---助手类添加");
super.handlerAdded(ctx);
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
System.out.println("Channel---助手类移除");
super.handlerRemoved(ctx);
}
}
CustomHandler
运行:
因为...谷歌浏览器请求了2次,一次是正常,一次是图标icon,所以...
本文来自博客园,作者:咸瑜,转载请注明原文链接:javascript:void(0)p/16007061.html