HTTP protocol
Version 0.9
GET /index.html
The server can only return html format, and the transmission process can only process text.
Version 1.0
Support content in any format, including image, video, binary, etc
POST command and HEAD command are introduced
HEAD command: this command is similar to get. It only returns header information and does not return all contents. It is fast. It is generally used to verify the effectiveness of the connection
Request header, status code, permission, cache, etc. are added
So what will he look like in 1.0?
request
GET / HTTP/1.0 User-Agent:Mozilla/1.0 Accept: */*
Response format
HTTP/1.0 200 OK Content-Type: text/plain Content-Encoding: gzip hello world
a, Content-Type
The server notifies the client of the current data format
Examples: text/html, image/png, application/pdf, video/mp4
The first level type is preceded by the second level type, separated by a slash; You can also add other parameters, such as encoding format.
Content-Type: text/plain; charset=utf-8
b,Content-Encoding
Indicates the method of data compression, gzip, compress, deflate
The field of the corresponding client is accept encoding, which represents the compression methods received
c. Shortcomings and problems
Each TCP connection can only send one request. After sending, the connection is closed. The use cost is very high and the performance is poor.
Connection: keep-alive - Nonstandard field
Version 1.1
Half a year after the launch of HTTP 1.0, version 1.1 also followed,
This version has been used until now. At present, most of our http requests use version 1.1
Here we use postman to request the common search engine cn.bing.com
request
GET / HTTP/1.1 User-Agent: PostmanRuntime/7.28.4 Accept: */* Postman-Token: 2e1942a8-9e7c-4c89-87d7-a46c11205b8c Host: cn.bing.com Accept-Encoding: gzip, deflate, br Connection: keep-alive
response
HTTP/1.1 200 OK Cache-Control: private Transfer-Encoding: chunked Content-Type: text/html; charset=utf-8 Content-Encoding: br Vary: Accept-Encoding P3P: CP="NON UNI COM NAV STA LOC CURa DEVa PSAa PSDa OUR IND" Set-Cookie: SUID=M; domain=.bing.com; expires=Sun, 21-Nov-2021 09:49:46 GMT; path=/; HttpOnly Set-Cookie: MUID=015C0F598C4C6F831C8A1FAC8D066E50; domain=.bing.com; expires=Thu, 15-Dec-2022 09:49:46 GMT; path=/ Set-Cookie: MUIDB=015C0F598C4C6F831C8A1FAC8D066E50; expires=Thu, 15-Dec-2022 09:49:46 GMT; path=/; HttpOnly Set-Cookie: _EDGE_S=F=1&SID=1793E6C6781468071F6CF633795E69AE; domain=.bing.com; path=/; HttpOnly Set-Cookie: _EDGE_V=1; domain=.bing.com; expires=Thu, 15-Dec-2022 09:49:46 GMT; path=/; HttpOnly Set-Cookie: SRCHD=AF=NOFORM; domain=.bing.com; expires=Mon, 20-Nov-2023 09:49:46 GMT; path=/ Set-Cookie: SRCHUID=V=2&GUID=A3776BC1B7E749699ADB5F7804C9FEE3&dmnchg=1; domain=.bing.com; expires=Mon, 20-Nov-2023 09:49:46 GMT; path=/ Set-Cookie: SRCHUSR=DOB=20211120; domain=.bing.com; expires=Mon, 20-Nov-2023 09:49:46 GMT; path=/ Set-Cookie: SRCHHPGUSR=SRCHLANG=zh-Hans; domain=.bing.com; expires=Mon, 20-Nov-2023 09:49:46 GMT; path=/ Set-Cookie: _SS=SID=1793E6C6781468071F6CF633795E69AE; domain=.bing.com; path=/ Set-Cookie: ULC=; domain=.bing.com; expires=Fri, 19-Nov-2021 09:49:46 GMT; path=/ Set-Cookie: _HPVN=CS=eyJQbiI6eyJDbiI6MSwiU3QiOjAsIlFzIjowLCJQcm9kIjoiUCJ9LCJTYyI6eyJDbiI6MSwiU3QiOjAsIlFzIjowLCJQcm9kIjoiSCJ9LCJReiI6eyJDbiI6MSwiU3QiOjAsIlFzIjowLCJQcm9kIjoiVCJ9LCJBcCI6dHJ1ZSwiTXV0ZSI6dHJ1ZSwiTGFkIjoiMjAyMS0xMS0yMFQwMDowMDowMFoiLCJJb3RkIjowLCJHd2IiOjAsIkRmdCI6bnVsbCwiTXZzIjowLCJGbHQiOjAsIkltcCI6MX0=; domain=.bing.com; expires=Mon, 20-Nov-2023 09:49:46 GMT; path=/ X-SNR-Routing: 1 X-Cache: CONFIG_NOCACHE X-MSEdge-Ref: Ref A: C567D165BB114CD98893F50FEF5FAEE8 Ref B: BJ1EDGE0716 Ref C: 2021-11-20T09:49:46Z Date: Sat, 20 Nov 2021 09:49:45 GMT The console only showsresponse bodies smaller than 10 KB inline. To view the complete body, inspect it by clicking Open.
- Persistent connection means that the tcp connection is not closed by default and can be reused by multiple requests. Most of the time, the browser allows six connections to the same domain name at the same time.
- The pipeline mechanism supports the client to send multiple requests and manage the order of requests. The server still returns the corresponding response results in the order of accepting requests.
- Content length, which is used to distinguish the important fields of the packet
- Support PUT, DELETE, PATCH and other commands
Shortcomings and problems
When some requests take a long time, the processing speed of subsequent requests will still be blocked. This phenomenon is called "queue head blocking" / "thread head blocking".
Version 2.0
Multiplexing is used to solve the problem of queue head blocking.
Multiplexing is not just on netty, it can be used in many places
Said so much on the code to operate it!!
Our writing idea is like this
- Write initialization server
- Writing custom initializers and custom processors
- Start postman to view the response results of the http we set
We have three classes here
- HttpServer initialization server
- MyHttpHandler custom processor
- MyHttpInitializer custom initialization
The first is the server
We need to set the master-slave thread model when initializing the server (commonly used in Netty) Set the startup parameters and the length of the blocking queue Set initialization
public class HttpServer { public static void main(String[] args) { //You can customize the number of threads EventLoopGroup bossGroup = new NioEventLoopGroup(1); // Number of threads created by default = number of CPU processors * 2 EventLoopGroup workerGroup = new NioEventLoopGroup(); ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .handler(new LoggingHandler()) //When the current connection is blocked, the BACKLOG represents the length of the event blocking queue .option(ChannelOption.SO_BACKLOG, 128) //Set the connection to remain active .childOption(ChannelOption.SO_KEEPALIVE, true) .childHandler(new MyHttpInitializer()); try { //Set to asynchronous start asynchronous close ChannelFuture future = serverBootstrap.bind(9988).sync(); future.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } finally { //netty's graceful shutdown means that it is closed slowly after everything is executed bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } }
Write initialization
The generic type of the inherited ChannelInitializer is Channel, which is used to set the outbound decoder and inbound encoder codec netty is used to encapsulate the decoder, so that we don't have to define decoding and coding every time
public class MyHttpInitializer extends ChannelInitializer<Channel> { @Override protected void initChannel(Channel channel) throws Exception { ChannelPipeline pipeline = channel.pipeline(); //First decode the corresponding request, and then decode the response //pipeline.addLast("decoder", new HttpRequestDecoder()); //pipeline.addLast("encoder", new HttpRequestEncoder()); //Of course, it is troublesome for us to decode and encode every time. netty also provides us with corresponding solutions. It is recommended to use this directly without error pipeline.addLast("codec", new HttpServerCodec()); //compressed data pipeline.addLast("compressor", new HttpContentCompressor()); //The aggregate complete information parameter represents the maximum value that can be processed. At this time, 512 kb pipeline.addLast("aggregator", new HttpObjectAggregator(512 * 1024)); pipeline.addLast(new MyHttpHandler()); } }
With initialization, we also need a processor Handler
netty helps us encapsulate the class DefaultFullHttpResponse that returns a complete http response We only need to set the protocol, status code and response information when reading, The response to the request can be completed by configuring the type and length of the response header
/* * Generic needs to be set to FullHttpRequest * Filter messages to process messages of this type * */ public class MyHttpHandler extends SimpleChannelInboundHandler<FullHttpRequest> { @Override protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest fullHttpRequest) throws Exception { //DefaultFullHttpResponse is a default full http response DefaultFullHttpResponse response = new DefaultFullHttpResponse( HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer("hello http netty demo".getBytes()) ); // We also need to set the response header // HttpHeaderNmaes can be used to set the request response header field // You can use the HttpHeaders headers = response.headers(); headers.add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.TEXT_PLAIN + ";charset=UTF-8"); headers.add(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes()); ctx.write(response); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); } }
Start result

Request response parameters seen by postman You can see the http1.1 protocol we set up Type text/plain length 47 Content to respond to the client hello http netty demo

Summary
- Understand the problems, advantages, disadvantages and advantages of each version of http
- Manually write a server response, and use postman to view the content of the response header we set
- Experience the convenience brought by the powerful encapsulation of netty