## 一、Http
建立在TCP传输协议之上的应用层协议,目前主流针对于WEB开发,Http协议应用非常广泛
,因此掌握HTTP协议的开发之重要。Netty如何基于Http协议进行开发,那么使用Netty的Http
协议也是异步非阻塞的。
### Http协议的特点:
简单:客户端请求服务器时只需要指定URL和携带的参数
灵活:Http协议允许传输任意类型的数据对象,传输内容有Http消息头中的Content-Type加以标记
### Http协议的组成
请求行
请求头
请求正文
### Http协议
响应状态种类
1xx :提示消息。表示请求已经接受继续处理
2xx :成功 表示请求已经接受成功
3xx :重定向 要完成的请求必须进行进一步的操作
4xx :客户端错误。可能是请求语法错误或者请求无法实现
5xx: 服务器错误。服务器未能处理请求(可能内部出现异常)
### 常见相应状态码
200 ok 成功
400 bad Request 错误请求语法,不能被服务理解
401 Unauthorized 请求未经授权
403 Forbidden 服务器收到请求,但是请求被服务器拒绝
404 Not Found 请求资源不存在
405 Method Not Allowed 请求方式不被允许,如只支持get请求,但客户端使用post
请求
500 Inernal Server Error: 服务器发送不可预期的错误
503 Servr Unavailable:服务器当前不能处理客户端的请求,一段时间后可能才能恢复正常
## 二、Netty与Http
### HttpHelloWorldServer
public final class HttpHelloWorldServer {
static final boolean SSL = System.getProperty("ssl") != null;
static final int PORT = Integer.parseInt(System.getProperty("port", SSL? "8443" : "8080"));
public static void main(String[] args) throws Exception {
// Configure SSL.
final SslContext sslCtx;
if (SSL) {
SelfSignedCertificate ssc = new SelfSignedCertificate();
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
} else {
sslCtx = null;
}
// Configure the server.
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.option(ChannelOption.SO_BACKLOG, 1024);
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new HttpHelloWorldServerInitializer(sslCtx));
Channel ch = b.bind(PORT).sync().channel();
System.err.println("Open your web browser and navigate to " +
(SSL? "https" : "http") + "://127.0.0.1:" + PORT + '/');
ch.closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
### HttpHelloWorldServerInitializer
public class HttpHelloWorldServerInitializer extends ChannelInitializer<SocketChannel> {
private final SslContext sslCtx;
public HttpHelloWorldServerInitializer(SslContext sslCtx) {
this.sslCtx = sslCtx;
}
@Override
public void initChannel(SocketChannel ch) {
ChannelPipeline p = ch.pipeline();
if (sslCtx != null) {
p.addLast(sslCtx.newHandler(ch.alloc()));
}
p.addLast(new HttpServerCodec());
p.addLast(new HttpHelloWorldServerHandler());
}
}
### HttpHelloWorldServerHandler
public class HttpHelloWorldServerHandler extends ChannelHandlerAdapter {
private static final byte[] CONTENT = { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' };
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.flush();
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
if (msg instanceof HttpRequest) {
HttpRequest req = (HttpRequest) msg;
if (HttpHeaderUtil.is100ContinueExpected(req)) {
ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE));
}
boolean keepAlive = HttpHeaderUtil.isKeepAlive(req);
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.wrappedBuffer(CONTENT));
response.headers().set(CONTENT_TYPE, "text/plain");
response.headers().setInt(CONTENT_LENGTH, response.content().readableBytes());
if (!keepAlive) {
ctx.write(response).addListener(ChannelFutureListener.CLOSE);
} else {
response.headers().set(CONNECTION, HttpHeaderValues.KEEP_ALIVE);
ctx.write(response);
}
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}