HTTP(超文本传输协议)请求和响应
在本文中,我们将讨论Internet的基本协议。
在1990年期间,蒂姆·伯纳斯·李(Tim Berners-Lee)是第一个提出名为“万维网”的项目的人。
最初的目的是在世界各地的科学家之间进行快速可靠的信息交换。
HTTP(超文本传输协议)最早是由欧洲核子研究组织(CERN)的蒂姆·伯纳斯·李(Tim Berners-Lee)实现的。
HTTP协议可以像许多其他协议一样在客户端和服务器模型中工作。
用来发起请求的Web浏览器称为客户端,将响应该请求的Web服务器软件称为服务器。
下面提到的是关于HTTP协议的一些要点和术语,在我们继续理解实际的完整http请求和响应之前,需要注意这些要点和术语。
- HTTP是应用程序层协议
- 如果请求中未提及,则默认端口为80
- 请求中的主机名不区分大小写
- 万维网联盟和Internet工程任务组都在HTTP协议的标准化中进行协调
- HTTP允许借助其间的中间层(例如网关,代理或者隧道)来改进其请求和响应
- 借助于称为URL(统一资源定位符)的URI(统一资源标识符)类型,可以使用HTTP协议请求的资源可用。
- TCP(传输控制协议)用于建立与HTTP使用的应用程序层端口80的连接(使用端口80进行http连接完全没有必要,但是如果URL中未明确提及,则假定使用端口80 )
- HTTP中的一系列请求和响应称为HTTP中的会话
- HTTP版本0.9是HTTP的第一个文档版本
- HTTP是一种无状态协议(这意味着每个连接都彼此独立。)
在本教程中,我设置了两个计算机。
一个将充当客户端,另一个将充当服务器,其中包含apache版本2.2.3-22.
设置了默认页面,该页面将显示此演示的“ hello”消息。
我们将启动从客户端到服务器的连接,并将捕获来自客户端的服务器上的所有流量,并查看正在发生的情况。
下面显示的是我在wget的帮助下从客户端(一台centos机器)发起的请求。
[root@theitroad1 ~]# wget http://192.168.0.103 --15:51:09-- http://192.168.0.103/ Connecting to 192.168.0.103:80... connected. HTTP request sent, awaiting response... 200 OK Length: 6 [text/html] Saving to: `index.html.7' 100%[=======================================>] 6 --.-K/s in 0s 15:51:09 (283 KB/s) - `index.html.7' saved [6/6]
让我们通过使用tcpdump捕获所有网络流量,看看服务器端客户端发起的http请求期间发生了什么。
[root@theitroad2 ~]# tcpdump -i eth0 -s0 -n -A host 192.168.0.104 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes 05:36:32.781066 IP 192.168.0.104.52802 > 192.168.0.103.http: S 3151905201:3151905201(0) win 5840 <mss 1460,sackOK,timestamp 6458684 0,nop,wscale 4> E..<..@[email protected]......... .b.<........ 05:36:32.781957 IP 192.168.0.103.http > 192.168.0.104.52802: S 3165795006:3165795006(0) ack 3151905202 win 5792 <mss 1460,sackOK,timestamp 6465077 6458684,nop,wscale 4> E..<..@[email protected]......... .b.5.b.<.... 05:36:32.783047 IP 192.168.0.104.52802 > 192.168.0.103.http: . ack 1 win 365 <nop,nop,timestamp 6458685 6465077> E..4..@[email protected]..... .b.=.b.5 05:36:32.784509 IP 192.168.0.104.52802 > 192.168.0.103.http: P 1:121(120) ack 1 win 365 <nop,nop,timestamp 6458685 6465077> E.....@[email protected]....... .b.=.b.5GET/HTTP/1.0 User-Agent: Wget/1.10.2 (Red Hat modified) Accept: */* Host: 192.168.0.103 Connection: Keep-Alive 05:36:32.784551 IP 192.168.0.103.http > 192.168.0.104.52802: . ack 121 win 362 <nop,nop,timestamp 6465080 6458685> E..4..@.@.$....g...h.P.B..2...B*...j....... .b.8.b.= 05:36:32.786377 IP 192.168.0.103.http > 192.168.0.104.52802: P 1:268(267) ack 121 win 362 <nop,nop,timestamp 6465082 6458685> E..?..@.@.#....g...h.P.B..2...B*...j.Q..... .b.:.b.=HTTP/1.1 200 OK Date: Thu, 21 Nov 2013 10:36:32 GMT Server: Apache/2.2.3 (Red Hat) Last-Modified: Thu, 21 Nov 2013 09:47:39 GMT ETag: "377709-6-f71984c0" Accept-Ranges: bytes Content-Length: 6 Connection: close Content-Type: text/html; charset=UTF-8 hello 05:36:32.787006 IP 192.168.0.103.http > 192.168.0.104.52802: F 268:268(0) ack 121 win 362 <nop,nop,timestamp 6465082 6458685> E..4..@.@.$....g...h.P.B..3...B*...j....... .b.:.b.= 05:36:32.787622 IP 192.168.0.104.52802 > 192.168.0.103.http: . ack 268 win 432 <nop,nop,timestamp 6458689 6465082>
让我们仔细检查一下tcpdump的输出。
为了便于理解,我将示例HTTP请求的tcpdump输出划分为以下不同步骤。
步骤1:通过客户端建立与服务器的TCP连接
像任何其他应用程序层协议一样,HTTP也可以在TCP上运行。
因此,客户端启动http连接的第一步是与http服务器建立TCP连接。
从上面的tcpdump输出的前三行中,我们可以清楚地看到这一点。
前三行表示初始的TCP握手。
阅读:TCP三向握手
如果看到tcpdump输出,则第一行是设置了“ S”标志的连接发起请求(因此是一个syn请求)。
第二个是从服务器到客户端的答复,其中设置了“ S&ACK”标志。
第三是来自客户端的“ ACK”回复,以完成三向握手。
请记住,到目前为止,我们仅完成了TCP连接的建立。
步骤2:由客户端向服务器发起HTTP GET请求
tcpdump输出中的第四行来自发起HTTP“ GET”请求的客户端。
客户端使用Get请求从服务器检索数据。
如果我们仔细查看了来自客户端的GET请求,它将显示一些信息,如下所示。
- 客户要求什么。例如,在我们的例子中,它是一个简单的“ /”。 GET“ /”,这种类型的请求告诉服务器检索根目录(的默认页面)。
- 它还告诉客户端使用的http版本。在我们的例子中是HTTP/1.0。
- 客户端通知服务器该请求正在使用哪种类型的用户代理(浏览器的类型,其版本,是否为其应用程序等。这部分是由用于启动连接的客户端软件发送的。在本例中,其“ Wget /1.10.2(Red Hat修改)”)
- 客户端通知服务器的另一个重要细节是客户端准备接受的数据类型。 HTTP允许所有MIME媒体类型。
在我们的示例中,客户准备接受任何类型的数据,因此其*/*
- HOST字段告诉服务器的主机名,客户机从该主机请求数据。
- 大多数客户端从服务器请求保持连接的保持连接类型。 Keep-alive用于保持客户端建立的tcp连接,从而减少了后续请求创建tcp连接的开销。尽管客户端从服务器请求保持连接的连接,但是它的服务器决定是否保持tcp连接处于活动状态(基于服务器配置)。
上面提到的所有GET请求参数如下所示(上面的tcpdump输出中也显示了该参数)。
05:36:32.784509 IP 192.168.0.104.52802 > 192.168.0.103.http: P 1:121(120) ack 1 win 365 <nop,nop,timestamp 6458685 6465077> E.....@[email protected]....... .b.=.b.5GET/HTTP/1.0 User-Agent: Wget/1.10.2 (Red Hat modified) Accept: */* Host: 192.168.0.103 Connection: Keep-Alive
Web服务器日志还将报告与我们在上面看到的相同的信息,让我们通过查看Web服务器日志中的get请求进行确认。
[root@theitroad2 ~]# tail -f /var/log/httpd/access_log 192.168.0.104 - - [21/Feb/2013:05:34:14 -0500] "GET/HTTP/1.0" 200 6 "-" "Wget/1.10.2 (Red Hat modified)"
步骤3:HTTP服务器对HTTP GET请求的响应
从客户端获取GET请求后,服务器将通过显示一些有关自身的信息以及有关客户端请求的数据和数据的元数据来进行响应。
- 服务器发送一个状态码(此状态码通知客户端软件有关请求结果的信息)。 HTTP使用了许多状态代码。我们将在本文后面的HTTP中看到一些常见的状态代码。讨论使用HTTP的所有状态代码不在本文讨论范围之内。
服务器以200的状态码和正在使用的http版本答复客户端。
在我们的例子中,它是HTTP /1.1.
状态码200表示请求成功。
2.日期指定发起响应的日期和时间
3.响应中提交的服务器告知正在使用的服务器软件(该字段在几乎所有Web服务器中均可修改。
这有时会违反安全性,因为它将向客户端显示服务器信息。
)
在我们的例子中,其Apache 2.2.3(Red Hat)
4.上次修改的字段将请求的数据的修改日期和时间通知客户。
5.Etag是一个字符串,用于标识所请求数据的修改。
这用于缓存。
这样可以提高Web缓存的质量。
Etag是Web服务器分配给所请求资源的特定版本的标识符。
6.使http成为出色协议的另一个重要因素是,我们可以请求所需的资源字节。
例如,如果要下载100M的文件,并且在断开连接之间进行下载,则以后可以通过在GET请求中指定从何处开始下载的字节范围来恢复下载。
在我们的例子中,服务器在响应中通知客户端它支持字节范围。
7.Content-Length指定以字节为单位的请求资源的大小。
在我们的情况下,它只是打印一个“ hello”。
因此,它的6个字节。
8.Connection:close,在我们的情况下表示完成此特定请求后将关闭连接。
9.Content-Type指定内容的类型。
在我们的示例中,它是一个简单的Text/HTML。
10.最后在这些标头的后面出现数据。
下面显示了来自http get响应中tcpdump输出的所有上述详细信息。
05:36:32.786377 IP 192.168.0.103.http > 192.168.0.104.52802: P 1:268(267) ack 121 win 362 <nop,nop,timestamp 6465082 6458685> E..?..@.@.#....g...h.P.B..2...B*...j.Q..... .b.:.b.=HTTP/1.1 200 OK Date: Thu, 21 Nov 2013 10:36:32 GMT Server: Apache/2.2.3 (Red Hat) Last-Modified: Thu, 21 Nov 2013 09:47:39 GMT ETag: "377709-6-f71984c0" Accept-Ranges: bytes Content-Length: 6 Connection: close Content-Type: text/html; charset=UTF-8 hello
在上面的示例中,我们已经看到了GET请求类型,让我们看到更多类型的HTTP请求类型。
HTTP头请求
HTTP头请求与GET请求非常相似。
这是了解特定URL上可用资源的完整详细信息的最简单方法,而无需下载整个数据。
例如,如果在上面的示例中使用HEAD请求,则将获得响应中所有标头的内容,但包含“ Hello”消息的页面除外。
这种请求仅用于检索数据的属性,而无需数据。
这样可以通过节省带宽为我们提供有关资源的信息。
HTTP发布请求
POST请求主要用于将数据从客户端发送到服务器。
让我们看一个从客户端到服务器的HTTP发布请求示例。
POST /my_data_send.php HTTP/1.1 Host: 192.168.0.105 User-Agent: ELinks/0.11.1 (textmode; Linux; 80x25-2) Referer: http://192.168.0.105/ Accept: */* Accept-Encoding: gzip Accept-Language: en Connection: Keep-Alive Content-Type: application/x-www-form-urlencoded Content-Length: 62 name=sarath&last=pillai&email=&telephone=&comments=
在上面显示的发布请求中,请求被发送到“ my_data-send.php”。
发送到服务器的数据还将包含我们在GET请求示例中看到的其他标头。
最后一行将确切的数据发送到服务器。
HTTP Put请求:
HTTP放置请求与发布请求非常相似。
PUT请求在指定的URI中发送或者创建资源。
如果该指定的URI中已经存在该资源,则它将更新该URI,否则将创建该资源。
HTTP删除请求:
HTTP删除请求删除指定URI上的指定资源。
绝对不建议为HTTP删除操作配置Web服务器。
但是,如果要启用此类功能,则比使用Web表单进行http POST操作的效果更好,该操作将删除资源。
HTTP跟踪请求
HTTP跟踪请求用于对http网页进行故障排除。
例如,假设某个网页没有以我们想要的方式在浏览器中加载。
然后,在这种情况下,http跟踪请求可用于检索服务器从客户端返回到客户端本身的完整请求。
在大多数Web服务器中,大多数都禁用这种请求类型。
主要原因是它与查看我们发送的请求的Web服务器日志非常相似。
下面提到一些众所周知的HTTP状态代码。
400
Http 400错误代码代表“错误请求类型”。
服务器收到任何形式的格式错误的请求时,服务器将响应400错误。
403
当禁止请求的资源时,服务器会显示此状态代码错误。
换句话说,可以说我们没有访问我们要访问的资源的权限。
404
http中最著名的错误代码是404.
它表示未找到错误。
在服务器上找不到请求的资源。
500
此错误代码500,用于通知客户端服务器中发生了一些内部错误。
但是此错误未在Web服务器中指定特定问题。
或者说Web服务器中的未知错误。