HttpRequestDecoder解析http协议时,Content-Length的重要性

NettyServer:

package wuwenlun.netty.chapter2.http;

import wuwenlun.netty.chapter2.ClientHandler;
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.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.string.StringEncoder;

public class NettyServer {
	public static void main(String[] args) {
		EventLoopGroup bossGroup = new NioEventLoopGroup(1);
		EventLoopGroup workerGroup = new NioEventLoopGroup();
		
		try {
			ServerBootstrap serverBootstrap = new ServerBootstrap();
			serverBootstrap.group(bossGroup, workerGroup)
						   .channel(NioServerSocketChannel.class)
						   .option(ChannelOption.SO_BACKLOG, 128)
						   .option(ChannelOption.SO_RCVBUF, 1024)
						   .option(ChannelOption.SO_KEEPALIVE, true)
						   .childHandler(new ChannelInitializer<NioSocketChannel>() {

								@Override
								protected void initChannel(NioSocketChannel ch) throws Exception {
									ch.pipeline().addLast(new HttpRequestDecoder());
									ch.pipeline().addLast(new HttpObjectAggregator(1024));
									ch.pipeline().addLast(new ServerHandler());
								}
							});
			
			ChannelFuture future = serverBootstrap.bind(8080).sync();
			
			future.channel().closeFuture().sync();
		} catch (InterruptedException e) {
			e.printStackTrace();
			bossGroup.shutdownGracefully();
			workerGroup.shutdownGracefully();
		}
	}
}

 

NettyClient:

package wuwenlun.netty.chapter2.http;

import java.nio.charset.Charset;

import io.netty.bootstrap.Bootstrap;
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.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

public class NettyClient {
	
	public EventLoopGroup group = null;
	public Bootstrap bootrap = null;
	
	public Bootstrap start() {
		group = new NioEventLoopGroup();
		bootrap = new Bootstrap();
		bootrap.group(group)
		.channel(NioSocketChannel.class)
		.option(ChannelOption.SO_KEEPALIVE, true)
		.option(ChannelOption.SO_SNDBUF, 3400)
		.handler(new ChannelInitializer<NioSocketChannel>() {

			@Override
			protected void initChannel(NioSocketChannel ch) throws Exception {
				ch.pipeline().addLast(new StringEncoder());
			}
		});
		
		return bootrap;
	}
	
	public static void main(String[] args) throws InterruptedException {
		ChannelFuture future = new NettyClient().start().connect("127.0.0.1", 8080).sync();
		String lineHeader = "GET /socketio?name=wuwenlun HTTP/1.1\r\n"+
						"Host: 127.0.0.1:8080\r\n"+
						"Connection: keep-alive\r\n"+
						"Upgrade-Insecure-Requests: 1\r\n"+
						"Content-Type: text/html\r\n"+
						"Content-Length: 20\r\n"+
						"User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36\r\n"+
						"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n"+
						"Accept-Encoding: gzip, deflate, sdch, br\r\n"+
						"Accept-Language: zh-CN,zh;q=0.8\r\n"+
						"\r\n";
		future.channel().writeAndFlush(lineHeader);
		Thread.sleep(15000);
		String content = "I Love You Forever";
		Charset charset = Charset.forName("UTF-8");
		content.getBytes(charset);
		future.channel().writeAndFlush(content);
		Thread.sleep(15000);
		future.channel().writeAndFlush("88");
		Thread.sleep(80000);
		future.channel().closeFuture().sync();
	}
}

 

ServerHandler:

package wuwenlun.netty.chapter2.http;

import java.nio.charset.Charset;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

public class ServerHandler extends ChannelInboundHandlerAdapter{

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg)
			throws Exception {
		System.out.println("服务端开始读取数据");
		if(msg instanceof ByteBuf) {
			ByteBuf buf = (ByteBuf)msg;
			String content = buf.toString(Charset.defaultCharset());
			System.out.println(content);
			ctx.channel().writeAndFlush("来自服务端发送:"+msg);
		}
	}

}

 

执行流程图:

现在回到Content-Length这个话题,当客户端发送的请求体内容长度没有达到Content-Length的数值时,会放弃往下执行,等待后面客户端发来的请求体内容,当数据总和达到Content-Length的数值时(包括前面的请求),则继续往下执行。那么你可能会提出一个问题,当前面的客户端请求(前面两次请求)没有达到Content-Length的长度时,而最后一次请求达到了(第三次请求)。第三次请求是如何知道前面两次请求的状态呢,不如数据分析到什么地步了啊,分析到哪里了啊。看netty的register分析文章。

 

转载于:https://my.oschina.net/u/2381372/blog/886039

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值