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分析文章。