NettyServer:html
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:java
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:web
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); } } }
執行流程圖:bootstrap
如今回到Content-Length這個話題,當客戶端發送的請求體內容長度沒有達到Content-Length的數值時,會放棄往下執行,等待後面客戶端發來的請求體內容,當數據總和達到Content-Length的數值時(包括前面的請求),則繼續往下執行。那麼你可能會提出一個問題,當前面的客戶端請求(前面兩次請求)沒有達到Content-Length的長度時,而最後一次請求達到了(第三次請求)。第三次請求是如何知道前面兩次請求的狀態呢,不如數據分析到什麼地步了啊,分析到哪裏了啊。看netty的register分析文章。app