3

java | http 协议

 1 year ago
source link: https://benpaodewoniu.github.io/2023/01/27/java216/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

java | http 协议

姑苏城外一茅屋,万树梅花月满天

netty 自带 http 解码器。

new HttpServerCodec()

使用 new HttpServerCodec() 会将数据解析成两个

  • DefaultHttpRequest
  • HttpContent

该处理器既是出站处理器也是入站处理器。

所以,接收数据可以写成

package com.redisc;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.DefaultHttpRequest;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;


@Slf4j
public class Server {

public static void main(String[] args) throws IOException {
NioEventLoopGroup boss = new NioEventLoopGroup();
NioEventLoopGroup worker = new NioEventLoopGroup();

try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.channel(NioServerSocketChannel.class);
serverBootstrap.group(boss, worker);
serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new LoggingHandler(LogLevel.DEBUG));
socketChannel.pipeline().addLast(new HttpServerCodec());
socketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof DefaultHttpRequest) { // 请求头,请求行

} else if (msg instanceof HttpContent) { // 请求体

}
}
});
}
});
ChannelFuture channelFuture = serverBootstrap.bind(8000).sync();
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
log.error("error", e);
} finally {
boss.shutdownGracefully();
worker.shutdownGracefully();
}

}
}

但是,每次我们用 if else 判断可能不优雅,比如,有时候,我们只需要请求体,所以可以简化成

直接在浏览器访问 http://127.0.0.1:8000/index.html

package com.redisc;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.*;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;

import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_LENGTH;


@Slf4j
public class Server {

public static void main(String[] args) throws IOException {
NioEventLoopGroup boss = new NioEventLoopGroup();
NioEventLoopGroup worker = new NioEventLoopGroup();

try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.channel(NioServerSocketChannel.class);
serverBootstrap.group(boss, worker);
serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new LoggingHandler(LogLevel.DEBUG));
socketChannel.pipeline().addLast(new HttpServerCodec());
socketChannel.pipeline().addLast(new SimpleChannelInboundHandler<HttpRequest>() {
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, HttpRequest msg) throws Exception {
// 返回响应

DefaultFullHttpResponse defaultHttpResponse = new DefaultFullHttpResponse(msg.protocolVersion(), HttpResponseStatus.OK);
byte[] b = "<h1>hello</h1>".getBytes();
defaultHttpResponse.headers().setInt(CONTENT_LENGTH, b.length);
defaultHttpResponse.content().writeBytes(b); // 不加这一句的话,chrome 就会一直等着,因为,他不知道数据长度是多长

// 写回响应
channelHandlerContext.writeAndFlush(defaultHttpResponse);
}
});
}
});
ChannelFuture channelFuture = serverBootstrap.bind(8000).sync();
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
log.error("error", e);
} finally {
boss.shutdownGracefully();
worker.shutdownGracefully();
}

}
}

通过使用简单处理器,SimpleChannelInboundHandler 中传递 HttpContent 里面就可以直接收 HttpContent 的内容了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK