Linux基础之HTTP的原理简介

一 、 跨Internet 的主机间通讯

在建立通信连接的每一端,进程间的传输要有两个标志:
IP址地址和端口号,合称为套接字地址 socket address
客户机套接字 地址定义了一个唯一的客户进程
服务器套接字 地址定义了一个唯一的服务器进程
Socket: 套接字,进程间通信IPC 的一种实现,允许位于不同主机(或同一主机)上不同进程之间进行通信和数据交换,SocketAPI出现于1983年
Socket API :封装 了内核中所提供的socket 通信相关的系统调用
Socket Domain :根据 其所使用的 地址

AF_INET :Address Family ,IPv4
AF_INET6 :IPv6
AF_UNIX :同一主机上不同进程之间通信时使用

Socket Type :根据使用的传输层协议

SOCK_STREAM:流,tcp套接字,可靠地传递、面向连接
SOCK_DGRAM:数据报,udp套接字,不可靠地传递 、无连接
SOCK_RAW:裸套接字, 无须tcp或tdp,APP直接通过IP

这张图片是关于CS套接字函数的图片个人感觉比较直观

CS套接字函数

套接字相关的系统调用:

socket():  创建一个套接字
bind() :绑定IP 和端口
listen() :监听
accept() :接收请求
connect() :请求连接建立
write() :发送
read() :接收
close():关闭连接

这里有一个Socket通信示例,是基于Python代码写的
服务器端的tcpserver.py

import socket
HOST='127.0.0.1'
PORT=9527
BUFFER=4096
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.bind((HOST,PORT))
sock.listen(3)
print('tcpServer listen at: %s:%s\n\r' %(HOST,PORT))
while True:
    client_sock,client_addr=sock.accept()
    print('%s:%s connect' %client_addr)
    while True:
        recv=client_sock.recv(BUFFER)
        if not recv:
        client_sock.close()
    break
    print('[Client %s:%s said]:%s'%(client_addr[0],client_addr[1],recv))
    client_sock.send('tcpServer has received your message')
sock.close()

客户端的tcpclient.py

import socket
HOST='127.0.0.1'
PORT=9527
BUFFER=4096
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect((HOST,PORT))
sock.send('hello, tcpServer!')
recv=sock.recv(BUFFER)
print('[tcpServer said]: %s' % recv)
sock.close()

上面的两个小程序可以简单是的调用socket进行通讯,接下来有一个基于socket的HTTP通信的图解。

HTTP基于socket通信过程

这个是HTTP通讯的过程图示

HTTP通讯过程图

在这里给大家大推荐两个很好用的学习web开发语言的网站,web有专门的HTML语言,这里就不介绍了
http://developer.mozilla.org/
http://www.w3school.com.cn/

现在HTTP协议任然使用的是1.1的版本,虽然有Google推出的2.0版本,但是任然没有大面积推行,所以这里只详细介绍1.1版本,想知道其他版本的话可以去Google下

http/1.1 :1997 年1月

  • 引入了持久连接(persistent connection ),即TCP 连接默认不关闭,可以被多个请求复用,不用声明Connection: keep-alive。对于同一个域名,大多数浏览器允许同时建立6 个持久连接
  • 引入了管道机制(pipelining ),即在同一个TCP 连接里,客户端可以同时发送多个请求,进一步改进了HTTP 协议的效率
  • 新增方法:PUT 、PATCH 、OPTIONS 、DELETE
  • 同一个TCP 连接里面,所有的数据通信是按次序进行的。服务器只能顺序处理回应,前面的回应慢,会有许多请求排队,造成"队头堵塞" (Head-of-line blocking) )
  • 为避免上述问题,两种方法:一是减少请求数,二是同时多开持久连接。网页优化技巧,比如合并脚本和样式表、将图片嵌入CSS 代码、域名分片(domain sharding )等
  • HTTP 协议不带有状态,每次请求都必须附上所有信息。请求的很多字段都是重复的,浪费带宽,影响速度

HTTP的工作机制:

  • 并行连接:通过多条TCP 连接发起并发的HTTP 请求
  • 持久连接:keep-alive, 长连接,重用TCP 连接,以消除连接和关闭的时延, 以事务个数和时间来决定是否关闭连接
  • 管道化连接:通过共享TCP 连接发起并发的HTTP 请求
  • 复用的连接:交替传送请求和响应报文(实验阶段)

URL的组成:

 <scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>

schame: 方案,访问服务器以获取资源时要使用哪种协议
user: 用户,某些方案访问资源时需要的用户名
password: 密码,用户对应的密码,中间用:分隔
Host: 主机,资源宿主服务器的主机名或IP 地址
port: 端口, 资源宿主服务器正在监听的端口号,很多方案有默认端口号
path: 路径, 服务器资源的本地名,由一个/ 将其与前面的URL 组件分隔
params: 参数,指定输入的参数,参数为名/ 值对,多个参数,用; 分隔
query: 查询,传递参数 给 程序,如数据库,用?分隔, 多个查询用& 分隔
frag: 片段, 一小片或一部分资源的名字,此组件在客户端使用,用#

网站访问量:

  • IP( 独立IP) :即Internet Protocol, 指独立IP 数。一天内来自相同客户机IP 地址只计算一次,记录远程客户机IP 地址的计算机访问网站的次数,是衡量网站流量的重要指标。
  • PV( 访问量): : 即 即Page View, 页面浏览量或点击量,用户每次刷新即被计算一次,PV 反映的是浏览某网站的页面数,PV与来访者的数量成正比,PV 并不是页面的来访者数量,而是网站被访问页面的数量。
  • UV( 独立访客) :即Unique Visitor, 访问网站的一台电脑为一个访客。一天内相同的客户端只被计算一次。可以理解成访问某网站的电脑的数量。网站判断来访电脑的身份是通过来访电脑的cookies 实现的。如果更换了IP 后但不清除cookies,再访问相同网站,该网站的统计中UV数是不变的

网站统计:http://www.alexa.cn/rank/ 但是个人感觉,不太准确,现在刷网站点击量的太多了

Web请求处理步骤

web请求处理步骤

接下来我们就对于上图进行详细的介绍:

(1)TCP三次握手进行连接

TCP三次握手

三次握手详细图解

上面是TCP三次握手的过程示意图,这里给大家一个详细的解释

  • 第一次
    • 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
  • 第二次
    • 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
  • 第三次
    • 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手

(2)建立连接

当我们输入这样一个请求时,首先要建立一个socket连接,因为socket是通过ip和端口建立的,所以之前还有一个DNS解析过程,把FQDN变成ip,如果url里不包含端口号,则会使用该协议的默认端口号。

(3)接受请求

接收客户端请求报文中对某资源的一次请求的过程,这里有关于Web的几个相应模型。
Web 访问响应模型(Web I/O)

  • 单进程I/O模型 :启动一个进程处理用户请求,而且一次只处理一个,多个请求被串行响应
  • 多进程I/O模型 :并行启动多个进程, 每个进程响应一 个连接请求
  • 复用I/O 结构 :启动一个进程,同时响应N个连接请求
    • 实现方法: 多线程 模型和事件驱动
    • 多线程模型:一个进程生成N 个线程,每线程响应一个连接请求
    • 事件驱动:一个进程处理N 个请求
  • 复用的多进程I/O 模型 :启动M 个进程,每个进程响应N 个连接请求,同时接收M* N个请求
Web访问响应模型

(3)应答请求

服务器对请求报文进行解析,并获取请求的资源及请求方法等相关 信息 ,根据 方法,资源,首部和可选的主体部分对请求进行处理
为了告知浏览器,,Web服务器首先传送一些HTTP头信息,然后传送具体内容(即HTTP体信息),HTTP头信息和HTTP体信息之间用一个空行分开。

元数据:请求报文首部
<method> <URL> <VERSION>
HEADERS 式 格式 name:value
<request body>
示例:
Host: FQDN 请求的主机名称
Server: Apache/2.4.7

(4)访问资源

服务器获取请求报文中请求的资源web 服务器,即存放了web 资源的服务器,负责向请求者提供对方请求的静态资源,或动态运行后生成的资源,资源放置于本地文件系统特定的路径:
DocumentRoot ---> /var/www/html
web 服务器资源路径映射方式:

  • (a) DocumentRootDocumentRoot
  • (b) alias
  • (c) 虚拟主机DocumentRoot
  • (d) 用户家目录DocumentRoot

(5)构建响应报文

一旦Web 服务器识别除了资源,就执行请求方法中描述中的动作,并返回响应报文。响应报文中 包含有响应状态码、响应首部,如果生成了响应主体的话,还包括响应主体。

1 )响应实体:如果 事务处理产生了响应主体,就将内容放在响应报文中回送过去。响应报文中通常包括:

  • 描述了响应主体MIME 类型的Content-Type 首部
  • 描述了响应主体长度的Content-Length
  • 实际报文的主体内容

2 )URL 重定向

web 服务构建的响应并非客户端请求的资源,而是资源另外一个访问路径,比如:

永久重定向:http://www.360buy.com
临时重定向:http://www.taobao.com

3 )MIME 类型

Web 服务器要负责确定响应主体的MIME 类型。有很多配置服务器的方法可以将MIME 类型与资源管理起来

  • 魔法分类:Apache web 服务器可以扫描每个资源的内容,并将其与一个已知模式表( 被称为魔法文件) 进行匹配,以决定每个文件的MIME 类型。这样做可能比较慢,但很方便,尤其是文件没有标准扩展名的时候
  • 显式分类:可以对Web服务器进行配置,使其不考虑文件的扩展名或内容,强制特定文件或目录内容拥有某个MIME类型
  • 类型协商:有些Web服务器经过配置,可以以多种文档格式来存储资源。在这种情况下,可以配置Web 服务器,使其可以通过与用户的协商来决定使用哪种格式(及相关的MIME类型)" 最好

(6)发送响应 报文

Web 服务器通过连接发送数据时也会面临与接收数据一样的问题。服务器可能有很多条到各个客户端的连接,有些是空闲的,有些在向服务器发送数据,还有一些在向客户端回送响应数据 。服务器 要记录连接的状态,还要特别注意对持久连接的处理。对非持久连接而言,服务器应该在发送了整条报文之后,关闭自己这一端的连接 。对持久连接来说,连接可能仍保持打开状态,在这种情况下, 服务器要正确地计算Content-Length首部,不然客户端就无法知道响应什么时候结束

(7)记录日志

最后 ,当事务结束时,Web 服务器会在日志文件中添加一个条目,来描述已执行的事物

(8)四次挥手断开连接

由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

  • (1) TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送。
  • (2) 服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。
  • (3) 服务器关闭客户端的连接,发送一个FIN给客户端。
  • (4) 客户端发回ACK报文确认,并将确认序号设置为收到序号加1。

示例:是采用curl工具抓取百度网站的包头,希望度娘见谅。

[root@VinnyWang ~]# curl -I www.baidu.com
HTTP/1.1 200 OK
Server: bfe/1.0.8.18
Date: Wed, 02 Aug 2017 06:30:19 GMT
Content-Type: text/html
Content-Length: 277
Last-Modified: Mon, 13 Jun 2016 02:50:01 GMT
Connection: Keep-Alive
ETag: "575e1f59-115"
Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
Pragma: no-cache
Accept-Ranges: bytes

这里给出一些,相应状态码:
状态代码由三位数字组成,第一个数字定义了响应的类别,且有五种可能取值。

1xx:信息性状态码,表示服务器已接收了客户端请求,客户端可继续发送请求。

100 Continue
101 Switching Protocols

2xx:成功状态码,表示服务器已成功接收到请求并进行处理。

200 OK 表示客户端请求成功
204 No Content 成功,但不返回任何实体的主体部分
206 Partial Content 成功执行了一个范围(Range)请求

3xx:重定向状态码,表示服务器要求客户端重定向。

301 Moved Permanently 永久性重定向,响应报文的Location首部应该有该资源的新URL
302 Found 临时性重定向,响应报文的Location首部给出的URL用来临时定位资源
303 See Other 请求的资源存在着另一个URI,客户端应使用GET方法定向获取请求的资源
304 Not Modified 客户端发送附带条件的请求(请求首部中包含如If-Modified-Since等指定首部)时,服务端有可能返回304,此时,响应报文中不包含任何报文主体。
307 Temporary Redirect 临时重定向。与302 Found含义一样。302禁止POST变换为GET,但实际使用时并不一定,307则更多浏览器可能会遵循这一标准,但也依赖于浏览器具体实现

4xx:客户端错误状态码,表示客户端的请求有非法内容。

400 Bad Request 表示客户端请求有语法错误,不能被服务器所理解
401 Unauthonzed 表示请求未经授权,该状态代码必须与 WWW-Authenticate 报头域一起使用
403 Forbidden 表示服务器收到请求,但是拒绝提供服务,通常会在响应正文中给出不提供服务的原因
404 Not Found 请求的资源不存在,例如,输入了错误的URL

5xx:服务器错误状态码,表示服务器未能正常处理客户端的请求而出现意外错误。

500 Internel Server Error 表示服务器发生不可预期的错误,导致无法完成客户端的请求
503 Service Unavailable 表示服务器当前不能够处理客户端的请求,在一段时间之后,服务器可能会恢复正常
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值