Http协议概述
1.什么是Http协议
HTTP是一个属于【应用层】的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。
2.HTTP协议的主要特点
1) 支持Client/Server模式
2)简单--客户向服务器请求,只需指定服务URL,携带必要的请求参数或者消息体
3) 灵活---HTTP允许输任意类型的数据对象
4)无状态--HTTP协议是无状态协议,无状态是指协议对于事务处理没有记忆能力。
3 HTTP协议的URL
HTTP url(URL 是一种特殊类型的URL,包含了用查找某个资源的足够信息)
http://host[":"port][abs_path]
其中,http表示要通过HTTP协议来定位网络资源;host表示合法的Internet主机域名或者IP地址:port指定一个端口号,为空则使用默认端口80;abs_pa出指定请求资源的URI,如果URL中没有给出abs_path,那么当它作为请求URI时,必须以/的形式给出,通常这点工作浏览器会自动帮我们完成。
4http请求消息(HttpRequest)
4.1http请求由三部分组成 如下
HTTP请求行;
HTTP消息头;
HTTP请求正文;
4.1.1HTTP请求行
请求行以一个方法符开头,以空格分开,后面跟着请求的URL和协议的版本,格式为:
Metchod Request-URL HTTP-Version CRLF
Metchod 表示请求方法
Request-URL 是一个统一资源标识符
HTTP-Version 表示请求的HTTP协议版本
CRLF 表示回车和换行
Metchod 表示请求方法,各方法作用 :
方法 | 描述 |
get | 请求获取Request-URL 所标识的资源 |
post | 在Request-URL所标识的资源的响应消息报头,常用于提交表单 |
head | 请求获取由Request-URL所标识的资源的响应消息报头 |
put | 请求服务器存储一个资源,并用Request-URL作为其标识 |
delete | 请求服务器删除 Request-url 所标识的资源 |
trace | 请求服务器回送收到的请求信息,主要用于测试或诊断 |
connect | 保留将来使用 |
options | 请求查询服务器的性能,或者查询与资源相关的选项和需求 |
4.1.2HTTP消息头 列表
名称 | 作用 |
Accept | 请求报头域用于指定客户端接受那些类型的信息 如: image/gif |
Accept-Charset | 请求报头域用于指定客户端接受的字符集 |
Accept-Encoding | 请求报头域 类似于Accept,但是它用于指定可接受的内容编码 |
Accept-Language | 请求报头域 类似于Accept,但是它用于指定一种自然语言 |
Authorization | 请求报头域 主要用于证明客户端有权查看 某个资源 |
Host | 发送请求时,该报头域是必需的,用于指定被请求资源的Internet主机和端口号 它通用是从HTTPURL中提取出来 |
User-Agent | 请求报头域允许客户端将它的操作系统,浏览器和其他属性告诉服务器 |
content-Length | 请求消息体的长度 |
Content-Type | 表示后面的文档属于什么MIME 类型 如 text/html |
Connection | 连接类型 |
5 HTTP 响应消息(HttpResponse)
http响应由三个部分组成分别是状态行,响应头,响应正文。
状态行是由:HTTP-Version, Status-Code,Reason-Phrase CRLF
分别表示:http版本 + 状态码 + 状态代码的文本描述
HTTP-Version:表示服务器HTTP协议的版本
Status-Code: 服务器返回的响应状态代码
状态代码:
1xx | 指示信息–表示请求已接收,继续处理 |
2xx | 成功–表示请求已被成功接收、理解、接受 |
3xx | 重定向–要完成请求必须进行更进一步的操作。 |
4xx | 客户端错误–请求有语法错误或请求无法实现。 |
5xx | 服务器端错误–服务器未能实现合法的请求。 |
响应头:包含服务器类型,日期,长度,内容类型等。
5 Netty http实列:
5.1 Netty Serverr
import com.jboss.MarshallingCodeCFactory; import com.netty.Serverr; import com.sun.jndi.toolkit.url.Uri; 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.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.LineBasedFrameDecoder; import io.netty.handler.codec.http.HttpRequestDecoder; import io.netty.handler.codec.http.HttpRequestEncoder; import io.netty.handler.codec.http.HttpResponseDecoder; import io.netty.handler.codec.http.HttpResponseEncoder; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import org.apache.log4j.spi.Configurator; import sun.security.krb5.Config; public class HttpServerText { public void bind(int port) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 1024) .childOption(ChannelOption.SO_KEEPALIVE, true) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new HttpResponseEncoder()); ch.pipeline().addLast(new HttpResponseDecoder()); ch.pipeline().addLast(new HttpServerHandler()); } }); ChannelFuture sync = bootstrap.bind(port).sync(); sync.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { new HttpServerText().bind(8081); } }
5.2 Netty Serverr 响应请求
import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.handler.codec.http.*; import io.netty.util.CharsetUtil; import org.apache.http.HttpConnection; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.HttpHeaders.Values; public class HttpServerHandler extends ChannelInboundHandlerAdapter { private HttpRequest request; public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { if(msg instanceof HttpRequest) { request=(HttpRequest)msg; System.out.println("Uri:" + request.uri()); } if(msg instanceof HttpContent) { HttpContent content = (HttpContent) msg; ByteBuf buf = content.content(); System.out.println(buf.toString(io.netty.util.CharsetUtil.UTF_8)); buf.release(); //HttpVersion.HTTP_1_1: http版本 //HttpResponseStatus.OK: http响应状态码 String res="OK"; FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(res.getBytes("UTF-8"))); //设置内容类型 response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain"); //设置内容长度 response.headers().set(HttpHeaderNames.CONTENT_LENGTH,response.content().readableBytes()); //开始给浏览器回复消息 ctx.write(response); ctx.flush(); } } public void channelReadComplete(ChannelHandlerContext context) throws Exception { context.flush(); } @Override public void exceptionCaught(ChannelHandlerContext context, Throwable cause) throws Exception { System.out.println(cause.getMessage()); context.close(); } } 结果