简介
HTTP(HyperText Transfer Protocol,超文本传输协议)协议是在万维网上客户端和服务器端进行通信的一种规范。
HTTP协议是基于C/S架构进行通信的,而HTTP协议的服务器端实现程序有httpd、nginx等,其客户端的实现程序主要是Web浏览器,例如Firefox、InternetExplorer、Google chrome、Safari、Opera等,此外,客户端的命令行工具还有elink、crul等。Web服务是基于TCP的,因此为了能够随时响应客户端的请求,Web服务器需要监听在80/TCP端口,这时客户端浏览器和Web服务器之间就可以通过HTTP协议进行通信了。
HTTP属于应用层协议,是无状态的协议,意味着客户端跟服务器不能长时间处于连接状态,一旦请求Request -> 响应Response过程完成,连接就会关闭。基于C/S模式,使用TCP连接进行可靠的传送。
HTTP连接过程
(1)建立TCP连接
在HTTP工作开始前,web浏览器向服务器发起连接请求,并建立建立。http协议是比tcp协议更高层次的应用层协议,根据规则,只有低层的协议建立连接才能进行数据通信。因此首先需要建立tcp连接,tcp连接的端口号一般是80。这里涉及TCP三次握手的知识,暂不介绍。
(2)客户端向服务器发送http请求行
HTTP请求协议的请求行:请求方法,url,协议版本。一旦建立连接,浏览器就会立即向服务器发起请求。
(3)客户端向服务器发送请求头信息
浏览器向服务器发送他的头部信息,头部信息的格式为name=value的格式发送,最后将以一个空行来告诉服务器发送的请求消息报头已经发送完毕。
如果是是post请求,还会发送请求体
(4)Web服务器应答 向客户端发送响应状态行
HTTP响应状态行:协议版本号 、 应答状态码、状态描述。浏览器向服务器发送请求以后,服务器会做出应答,如HTTP/1.1 200 OK。
(5)Web服务器发送应答头信息
就像客户端向服务器发送自己的头部消息一样,服务器也向客户端发送自己的数据和请求的文档,并以一个空行表示头部信息已经全部发送完毕。
(6)Web服务器向客户端发送数据
这时候web服务器会以Content-Type应答头部信息所描述的格式发送用户所请求的实际数据。
(7)服务器关闭TCP连接
一旦web服务器向客户端发送了请求数据,服务器就要断开TCP连接。
如果浏览器和服务器的头部信息中加入了“Content-Type:keep-alive”,那么在服务器发送数据之后,TCP连接还是保持着打开状态,HTTP发送下一个请求的时候可以直接发送,不需要再次建立TCP连接。保持连接节省了为每个请求建立新的连接所需要的时间,还节约了网络带宽。
HTTP请求报文与响应报文格式
- 请求报文
请求行: 请求方法 URL HTTP协议版本
请求头:包括浏览器类型、客户端接收的编码格式、客户端可接收的自然语言、cookie,缓存设置、连接类型(长连接还是短连接)等消息
请求体:一般不在GET方法中使用,而是在POST方法中用于存放提交的表单数据 - 响应报文
状态行:协议版本 状态码 状态码描述
响应头:缓存设置,连接类型,服务器类型,编码格式等消息
响应体:服务器返回给客户端的信息
GET请求和POST请求中的请求参数问题
在get请求中,把请求参数放在请求体中,或者在post请求中,将请求参数放在url中,都是不会报错而且正常请求与响应数据,那么我们能正确接收到请求参数吗?
以php代码测试:
curl.php
<?php
$ch = curl_init(); //初始化CURL连接
$url = "http://localhost/template.php?a=1";
curl_setopt($ch, CURLOPT_POSTFIELDS, "bbbbbbbb");//设置请求体
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
//curl_setopt($ch, CURLOPT_HTTPGET, 1); //GET请求
curl_setopt($ch, CURLOPT_POST, 1); //POST请求
curl_setopt($ch,CURLOPT_HEADER,0);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
$output = curl_exec($ch); //执行CURL请求
if($output === FALSE ){
$result = false;
}else{
$result = $output;
}
curl_close($ch); //关闭CURL连接
var_dump($output);
template.php
<?php
$param["getData"] = $_GET;
$param["postData"] = $_POST;
$param["bodyData"] = @file_get_contents('php://input');
$param["method"] = $_SERVER['REQUEST_METHOD'];
echo json_encode($param);
访问curl.php,会发送一个post请求给template.php,结果如下:
把上述代码post请求方式注释掉,放开get请求注释,发送get请求,结果如下:
分析结果,可以看出发送post请求,将数据放在url中,接收端可以通过get方式接受到url中的参数,并且请求体中的数据也能正常接受到(图1中的postData就是post方式接受的参数,bodyData就是接受请求体中的参数)。
但是在get请求中,把请求参数放到请求体中,是无法接受到请求参数的,但是放在url中的参数可以通过get请求正常接收。