本文会介绍以下知识:
- TCP/IP HTTP关系
- HTTP协议概述
- POST请求和GET请求
- Cookie和Session
- 数据传输时的加密
- HTTPS简介
前面见了这么多协议与层,首先我们将他们梳理一下。
一、TCP/IP 与HTTP的关系
-
TCP/IP是个协议组,可分为三个层次:网络层、传输层和应用层。
在网络层有IP协议、ICMP协议、ARP协议、RARP协议和BOOTP协议。
在传输层中有TCP协议与UDP协议。
在应用层有FTP(主机之间传输文件,不受操作系统的限制)、HTTP、TELNET、SMTP、DNS等协议。 - 因此,HTTP本身就是一个协议,是从Web服务器传输超文本到本地浏览器的传送协议。HTTP是应用层协议,主要解决如何包装数据。WEB使用HTTP协议作应用层协议,以封装HTTP 文本信息,然后使用TCP/IP传输层协议将它发到网络上。
为了更好理解,把IP想像成一种高速公路,它允许其它协议在上面行驶并找到到其它电脑的出口。TCP和UDP是高速公路上的“卡车”,它们携带的货物就是像HTTP,文件传输协议FTP这样的协议等。
虽然HTTP本身是一个协议,但其最终还是基于TCP的,每个HTTP请求都需要通过TCP建立连接,然后在连接的基础上请求/响应。HTTP/1.0为每一次HTTP的请求/响应建立一条新的TCP链接,HTTP/1.1将只建立一次TCP的链接而重复地使用它传输一系列的请求/响应消息,因此减少了链接建立的次数和经常性的链接开销。 - Socket
实际上socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API)。Socket的出现只是使得程序员更方便地使用TCP/IP协议栈而已,是对TCP/IP协议的抽象。
建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket ,另一个运行于服务器端,称为ServerSocket 。
套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。
1、服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。
2、客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。
为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
3、连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。
二、HTTP协议概述
在OSI七层模型中,HTTP协议处于最顶层的应用层。通过浏览器访问网页就使用了HTTP协议。使用HTTP协议时,客户端首先与服务端的80端口建立TCP连接,然后在这个连接的基础上进行请求和应答,以及数据的交换。
HTTP有两个常用的版本,1.0和1.1。主要区别在于在HTTP1.0中每次请求和应答都会新建一个TCP连接;而从HTTP1.1开始,运行在一个连接上发送多个命令和应答。因此,大幅减少了TCP连接的建立和断开,提高了效率。
1. HTTP请求报文
- 请求行(request-line):(Get /homepage.html HTTP/1.1)
请求方法
请求资源路径
协议类型和版本
- 请求头(header):若干消息头
请求头中至少包含如下信息:
客户端要访问的服务器主机地址
Host: m.baidu.com
还可以包含如下信息:
User-Agent: iPhone AppleWebKit //客户端的类型,客户端
的软件环境
Cookie:客户端通过这个头可以向服务器带数据
content-type=text/html //发送的数据类型
Accept: text/html //客户端所能接收的数据类型
Accept-Language: zh-cn //客户端的语言环境
Accept-Encoding: gzip //客户端支持的数据压缩格式
Connection: Close //访问结束后,是否断开连接
Accept-Charset:GB2312,utf-8;q=0.7,*;q=0.7 //客户端采用的编码格式
- 空行(blank-line):
最后一个请求头之后是一个空行,分割请求头 - 请求包体
这个部分不在GET方法中使用,在POST方法中使用。POST方法适用于客户提交表单的场合。与请求数据相关的最常用的请求头是Content-Type和Content-Length。
2.HTTP响应报文
- 状态行:HTTP/1.1 200 OK(CRLF)
协议和版本
状态码
状态码的描述
常见状态码:
100-199 : 表示成功接收请求, 要求客户端继续提交下一次请求才能完成整个处理过程
200-299: 表示成果接收请求并已完成整个处理过程. 常用200
300-399: 为完成请求, 客户需进一步细化需求: 例如: 请求的资源已经移动一个新地址, 常用302(重定向), 307和304(拿缓存)
400-499: 客户端的请求有错误, 包含语法错误或者不能正确执行. 常用404(请求的资源在web服务器中没有) 403(服务器拒绝访问, 权限不够)
500-599: 服务器端出现错误
200 正常 表示一切正常, 返回的是正常请求结果
201 Created
302/307 临时重定向 指出请求的文档已被临时移动到别处, 此文档的新的url在location响应头中给出
304 未修改 表示客户机缓存的版本是最新的, 客户机应该继续使用它
400 Bad Request
403 禁止 服务器理解客户端请求, 但拒绝处理它, 通常用于服务器上文件或目录的权限设置所致
404 找不到 服务器上不存在客户机所请求的资源
500 服务器内部错误 服务器端的cgi, asp, jsp等程序发生错误
- 响应头:包含了对服务器的描述,对返回数据的描述
Server: Apache/2.4.10 (Unix) PHP/5.5.20 //服务器的类型
Content-Type: text/html //返回数据的类型
Content-Length: 660 //返回数据的长度
Date: Thu, 04 Jun 2015 19:31:50 GMT //响应时间
ETag: "294-4e1862f57e7c0" //ETag(HASH值,用于检测本地资源和服务器资源是否一致)
- 空行(blank-line):
和请求报文空行一样 - 响应包体(body)
服务器返回给客户端的数据。
三、URL
URL,全称是UniformResourceLocator,中文名叫统一资源定位符,是互联网是用来标识某一处资源的地址。下面介绍URL的组成部分:
scheme://user:password@host:port:/path;parameters?query#fragment
URL1:http://www.jianshu.com/p/a76303c7f262
URL2:ftp://xun:listen@ftp.pre.ai.mit.edu.pub.gnu
URL3:mailto:xun@whitehouse.gov
URL4:http://www.joes-hardware.com/hammers;sale=false/index.html;graphics=true
URL5:http://www.joes-hardware.com/inventory-check.cgi?item=12371&color=blue
URL6:http://www.joes-hardware.com/tools.html#dirlls
- scheme:访问URL的方案,访问资源服务器时所使用的协议。如URL1,是通过HTTP协议去访问的,同理URL2是通过ftp协议去访问,URL3是通过SMTP去访问。
- user:某些方案访问资源时需要用户名,默认匿名(也就是没有啦,不用输入)。如URL2和URL3中,我们的用户名就是xun。
- password:访问资源服务器时,可能需要密码与用户名用:
隔开。如URL2中,密码就是listen。 - host:资源服务器的主机名或IP地址。在URL1,www.jianshu.com 会被DNS解析出IP地址。
- port:资源服务器监听的端口号,大部分方案有默认端口,如HTTP端口号默认为80。
- path:服务器上的资源本地名,由一个/
与前面的URL组件分开来(路径组件的语法和方案有关)。如URL1,其path为p/a76303c7f262 - parameterString:某些方案会用它来指定输入参数。参数为key=value,与其余部分用;隔开。如URL4中,参数为sale=false/index.html;graphics=true。
- query:某些方案会用这个组件传递参数以激活应用程序。查询组件没有通用格式,用?与其余部分分隔开来,并用&
连接查询条件。如URL5,其查询条件为item=12371&color=blue - fragment:一小片或一部分资源的名字。引用对象时,不会将fragment传给服务器,这个字段是客户端内部使用的。通过#与其他部分分隔开来。如URL6中,drills引用了tools.html
中的一部分,这个部分的名字叫drills。
四、POST请求和GET请求区别
GET请求数据参数会拼接在URL中,一是不安全太容易被发现,二是URL的长度有限制。而POST请求会把数据放到请求体中,安全稍微提高那么一点,因为截获报文扔能看到,长度没有限制。
GET请求可以被缓存,比如登录页面,如果通过GET请求提交,用户名和密码都会被添加到URL上,这个页面可以被缓存下来,或在历史记录中被查看。
尽管POST不会被直接看到,但是如果截获报文,仍然能看到body体中的数据,所以最安全的方式还是加密。从语义的角度回答:
- get,用于获取资源,需要是安全的、幂等的、可缓存的。
- post,用于处理资源,是非安全的、非幂等的、不可缓存的。
三个特性说明:
- 安全性:不应该引起server端任何的状态变化。即使是多次操作。GET、HEAD、OPTIONS都是安全的。
- 幂等性:同一种请求方法执行一次和执行多次的效果完全相同。
- 可缓存:请求是否可以被缓存。在发送一个http请求的时候,路径是不确定的,可能会通过网关、代理服务器,代理服务器是会有缓存的,这种缓存性是官方文档定义的一种规范,我们可以遵从也可以不遵从,大多数我们是遵从的。所以我们在执行请求的时候可能请求到的是一个缓存结果。
五、加密
加密分为两种,对称加密和非对称加密。在解释这两个概念之前,我们先看看简单的加密、解密过程。
- 所谓的对称,就是指加密和解密的密钥相同,而非对称自然就是指不同。
举个对称加密的例子。假设现在加密算法是加法,解密算法是减法,传输数据是10,密钥是1。发送方对数据进行加密10+1=11,解密方对接收到的数据11进行解密,11-1=10。于是得到了加密前的数据。 - 在非对称加密中,通过公钥加密的数据只能通过私钥解密,通过私钥加密的数据只能通过公钥解密。
常见的非对称加密的算法是RSA算法,它主要利用了“将两个素数求乘积容易,但是将乘积分解为两个素数很难”这一思想。具体原理可以参考:RSA 加密
质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数(2,3,5,7,11,13等);否则称为[合数]。
对称加密的优点是速度快,但是假设密钥由服务器保存,如何将密钥由服务器安全的发送到客户端,就是需要考虑的问题了。因此实际的网络传输中,经常采用对称加密和非对称加密相结合的方式:服务端通过非对称加密将对称密钥发送给客户端,然后双方用这个密钥通过对称加密传输数据。
六、HTTP的特点
1. 无连接
每次请求都需要三次握手四次挥手来建立断开连接。
解决方案:持久连接。
具体的使用:
- 如何使用持久连接?
在请求头中设置:
Connection : keep-alive //表示为持久连接
time : 20 //表示持续时间20秒
max : 10 //这条连接最多可以发生多少个http请求 - 如何判断一个请求是否结束?
通过响应头:
- Content-length :1024 ,通过相应头中该字段来判断客户端是否收到了这么多内容,来判断。
- 我们通过post请求数据时,往往需要多次响应,来返回数据的,这时每个返回报文的响应头中都会有个字段chunked,最后一个响应块的响应头中的chunked字段对应为空。所以,我们可以通过判断chunked是否为空来判断是否结束了
2. 无状态
HTTP是一种无状态的协议,一旦数据交互完毕,客户端与服务端的连接就会断开。但有些时候,我们需要持久的保存一些信息,比如上次连接的信息,如用户信息:用户名、密码等。
Cookie就是这样一种机制,它可以弥补HTTP无状态的不足。在Session出来之前,基本所有网站都是采用Cookie来跟踪会话。Cookie不能跨域使用。
Session是服务端记录客户端状态的一种机制,使用上比Cookie简单一些,相应的也会增加服务器的存储压力。
- cookie数据存放在客户的浏览器上,session数据放在服务器上;
- cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用session;
- session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能。考虑到减轻服务器性能方面,应当使用COOKIE;
- cookie总大小在客户端也有限制(基本是4k),Firefox和Safari允许cookie多达4097个字节,包括名(name)、值(value)和等号。
- 每个域名cookie有限制,Firefox每个域名cookie限制为50个。
NSURL:确定要访问的资源
NSURLRequest:根据 URL建立请求,向服务器索要数据
:建立网络连接,将请求(异步)发送给服务器
资料:
2-cookies和session(个人附加token)
[面试∙网络] TCP/IP(六):HTTP 与 HTTPS 简介
3-http协议(2017-04-21更新请求方法)