一.http协议
1.http协议的初步认识
http是在传输层基于tcp实现的应用层协议,默认端口号为80端口;
http是一个简单的请求响应协议;
http是一个明文字符串传输协议;
2.http协议的特点
(1)支持客户机/服务器模式;
(2)简单快速,客户端每次向服务器请求资源时,只需要指定请求方法和路径;
(3)无连接:每次连接只处理一个请求,服务器处理完客户端的请求,并收到客户端的应答后,断开连接;
(4)无状态:协议不关心客户端的状态,只是根据请求进行处理,并不会记录任何信息;
(5)灵活,http允许传输任意类型的数据对象;
3.http协议的版本
0.9
只支持GET请求,服务器只能响应HTML格式的资源;
1.0
规范了协议格式,支持了更多的请求方法如POST、HEAD,支持了多媒体资源的传输;
仍然是每次收到新的请求后处理后断开连接,当继续请求资源时,必须新建连接;
1.0版本对于性能改进不大。
1.1
在1.0的基础上,针对传输性能进行大量改进,支持了长连接,即在同一个tcp连接中,客户端可以同时发送多个请求,进一步提高了传输效率;
提供了更加完善的缓存控制;
存在的问题:
管线化传输的队头阻塞问题,在同一个tcp连接中,所有数据通信按顺序进行,服务器只能按照顺序进行处理,前面处理地慢,会有很多请求排队,造成请求阻塞;
传输数据是明文,不够安全;
每次传输仍然需要重新连接;
头部数据太长;
2.0
重新定义了http协议,采用二进制的数据传输方式;
复用tcp连接,在同一个连接中,可以同时发送多个请求,哪个请求先处理好就发送响应正文,不用按顺序进行,避免了队头阻塞问题;
允许服务器未经请求,主动向客户端发送资源;
引入头部压缩机制;
4.http协议的格式
(1).首行
请求和响应的关键信息的简单描述
请求首行
组成:请求方法 URL 协议版本\r\n
示例:
GET www.baidu.com HTTP/1.1
常见的请求方法:
GET:从服务端获取实体资源,请求没有正文,也可以提交数据,但提交的数据在url中
POST:向服务器提交数据进行处理请求(例如提交表单和上传文件),数据包含在请求体中,POST请求可以建立新资源或者修改已有资源
PUT:向服务器提交数据取代指定的文档内容
HEAD:类似于GET请求,但返回的响应中没有具体内容,用于获取报头
URL:
统一资源定位符,用于唯一标识并定位网络上某主机上的某个资源,URL是URI的子集
URL的组成:
协议名称://用户名:密码@域名或者IP地址:端口号/资源路径?查询字符串#片段标识
示例:http://user:passwd@www.baidu.com:80/s?ie=UTF-8&wd=c++#first
域名:服务器的别名,通过域名访问服务器时需要通过域名解析才能拿到服务器的IP地址,从而访问服务器的资源
资源路径:一个相对根目录
查询字符串:提交给服务器的数据,由一个个key=val形式的键值对构成,键值对之间用&间隔
注意:在查询字符串中可能会有特殊字符,会与URL中的特殊字符冲突,所以需要经过urlencode进行编码,通过urldecode进行解码
URI:统一资源标识符,用于唯一标识网络上某主机上的某个资源
响应首行
组成:协议版本 响应状态码 状态码描述\r\n
示例:
HTTP/1.1 200 OK
响应状态码:
服务器向客户端反馈自己的处理结果
分类:
1XX:一些描述信息
2XX:标识本次请求正确处理
3XX:重定向,需要进一步的操作以完成请求,本次请求的资源被移动到了新的链接处,但是原链接依然可用。
4XX:客户端错误
5XX:服务器错误
常见的响应状态码:
101:协议切换 200:OK
301:永久移动,请求的资源被永久移动到新的URL,下次请求时直接定位到新的URL
302:临时移动, 请求的资源临时被移动,下次请求时继续使用原来的URL
404:服务器无法根据客户端的请求找到资源
502:客户端发出请求,但作为网关或者代理工作的服务器尝试在向远程服务发送请求时,没有发送成功
503:系统超载或维护
504:客户端发出请求,但作为网关或者代理工作的服务器尝试在向远程服务发送请求时,请求发送成功,
但是迟迟没有得到响应
(2).头部
关于请求/响应/正文的一些描述字段,字段之间以\r\n间隔
典型头部字段:
Connection:控制长短连接,closed表示短连接,keep-alive表示长连接
Referer:记录本次请求的来源路径
Content-Type:正文的数据格式
Content-Length:正文的长度,是http用于解决粘包问题的关键字段
Location:用于指定重定向的新链接地址,与以3开头的状态码搭配使用
Cookie与Set-Cookie:维护http通信状态
Cookie和Set-Cookie的使用流程:
当客户端开始登录,服务端验证登录成功后,通过Set-Cookie字段设置Cookie信息(用户名,状态…)返回给客户端;客户端收到响应后,把Set-Cookie字段中的cookie信息保存起来,下次请求服务器时从cookie文件中读取出Cookie信息,通过Cookie字段发给服务端
cookie存在安全隐患,在网络传输中可能会被劫持,因此引入了session.
session是服务端为每个客户端建立的会话,当客户端登录成功后,创建会话,在会话中记录客户端的用户信息和状态,通过Set-Cookie字段将session-id返回给客户端,而将用户的隐私信息一直保存在服务器上,防止泄露;下次请求服务器时,服务器通过Cookie字段中的session-id在自己的session表中进行查找是否有对应id的session信息,如果有登录成功,没有登录失败。
cookie与session的区别:
cookie是维护http通信状态的技术,把关键信息保存在客户端,每次请求服务器时,从cookie文件中读取数据并发送给服务端,但是cookie存在安全隐患;
session是解决cookie安全隐患的技术,将关键信息保存在服务器上,把session-id发送给客户端,作为cookie保存起来,往后请求传输session-id即可,解决了cookie的安全隐患
(3).空行
由\r\n组成,用于间隔头部和正文
(4).正文
客户端提交给服务端,或者服务端响应给客户端的数据;
二.https协议
https协议并不是一个新的协议,而是在http协议的基础上使用ssh进行了一层加密,目的是实现数据的安全传输。
1.安全传输需要考虑的两个问题
身份验证问题和数据加密问题
(1)身份验证实现
通过CA认证实现,
CA认证:
通信双方在通信前先到权威机构请求给自己颁发一个CA证书,
CA证书(权威机构信息,自己的信息,…)
通信两方建立连接后,在通信之前先将证书发送给对方收到对方的证书后,查看这个权威机构是否是自己信任的权威机构,如果是,则到权威机构进行这个公司的身份验证验证通过后进行通信,不通过可以自行选择是否添加信任。
身份验证通过,但通信仍然可能会被监听,存在安全隐患,因此需要加密传输
(2)数据加密实现
三种加密方式:
对称加密
加密和解密使用相同的密钥
优点是加解密效率高,缺点是密钥一旦被劫持则加密形同虚设
非对称加密
加密和解密使用不同的密钥
实现流程:
通信过程中,每一端在通信前都生成一对密钥(公钥和私钥)。在通信前,将公钥发送给对端,对端收到使用的公钥进行数据加密然后传输,自己收到数据后,使用私钥进行解密。
实现算法:RSA加密算法
优点是安全度更高,缺点是加解密效率低下
混合加密
通信双方,先使用非对称加密保护对称密钥的协商过程,对称密钥协商完毕后,使用对称密钥加密传输。
2.ssl加密流程
将CA认证和混合加密结合
(1).服务器先生成一对密钥(公钥和私钥),到权威机构使用公钥请求颁发一个证书(权威机构信息,本身机构信息,公钥信息,过期时间…);
(2).通信双方建立连接后,服务器把证书发送给客户端;
(3).客户端对证书进行解析,根据证书中的信息进行身份验证;
(4).身份验证通过后,使用公钥加密(一个随机数+自己支持的对称加密算法列表)发送给服务器;
(5).服务器收到数据使用私钥进行加密,并给客户端回复一个随机数+自己支持的对称加密算法列表;
(6).双方通过自己的随机数与对方发送过来的随机数配合对称加密算法表进行计算得到一个对称密钥;
(7).之后的通信使用对称密钥进行通信
三.UDP协议
1.协议段格式
16位源端/对端端口:用于描述识别通信两端的进程
16位数据报长度:表示整个数据报(UDP首部+UDP数据)的最大长度,能够存储的最大数字为65535,UDP报文总大小不超过64k
16位校验和:采用二进制反码求和算法,校验接收方接收到的数据和发送方发送的数据是否一致
2.协议特性
(1)无连接
? 通信时不需要建立连接,只要知道对方地址就可以发送数据,减少了开销和发送数据之前的时延
(2)不可靠
? 不保证数据安全有序到达对端
(3)面向数据报,适合一次性传输少量数据,传输的数据有最大长度限制
? 应用层给UDP多长的报文,UDP照样发送,即一次发送一个完整报文;
? 在udp发送数据时,sendto发送的数据会被送到发送缓冲区中,而udp协议不会等待,直接对数据封装头部,进 行发送。在udp接收数据时,收到的数据会被放到接收缓冲区中,而udp保证数据是整条交付的,不会出现半条 或多条交付;
(4)udp无拥塞控制,适合很多实时应用
3.对上层编程的影响
(1)不保证安全到达,需要应用层使用tcp所使用的一些机制实现保证数据安全到达;
(2)不保证有序到达,需要在应用层进行包序管理;
(3)udp报文有最大长度限制,报文最大长度小于64k,所以发送大块数据时,需要在应用层进行数据分包然后发 送;
(4)udp实现的是整条交付,因此接收方的接收缓冲区必须定义的足够大,能一次性取出一条数据。
四.TCP协议
1.协议段格式
16位源端/对端端口:用于描述识别通信两端的进程
32位序号/确认序号:进行包序管理
4位TCP报头长度:
表示该TCP头部有多少个32位bit(有多少个4字节); 所以TCP头部最大长度是15 * 4 = 60字节,最小为20字节
6位标志位:
URG: 紧急指针是否有效
ACK: 确认号是否有效
PSH: 提示接收端应用程序立刻从TCP缓冲区把数据读走
RST: 对方要求重新建立连接; 我们把携带RST标识的称为复位报文段
SYN: 请求建立连接; 我们把携带SYN标识的称为同步报文段
FIN: 通知对方, 本端要关闭了, 我们称携带FIN标识的为结束报文段
16位窗口大小:用于实现滑动窗口机制
16位校验和:采用二进制反码求和算法,校验接收方接收到的数据和发送方发送的数据是否一致
16位紧急指针: 标识哪部分数据是紧急数据
2.协议特性
(1)面向连接
? 连接管理+状态管理
? 连接管理:三次握手建立连接,四次挥手断开连接
? 三次握手建立连接:
? 客户端发送syn请求后,进入SYN_SENT状态;
? 服务端最初的监听套接字是closed状态,调用listen后进入LISTEN状态,当服务端收到syn请求后,新建通信套 接字,进行确认回复,回复之后进入SYN_RCVD状态;
? 当客户端收到服务端的ack回复和syn请求后,向服务端发送ack回复,发送之后客户端进入ESTABLISHED状 态;
? 客户端收到ack后进入ESTABLISHED状态;
? 四次挥手断开连接:
? 主动关闭方调用close(fd)或者shutdown的写操作后向被动关闭方发送fin包,发送之后进入FIN_WAIT1状 态;
? 被动关闭方收到fin包后进行ack回复,之后进入CLOSE_WAIT状态;
? 主动关闭方收到ack后进入FIN_WAIT2状态;
? 被动关闭方调用close(fd)或者shutdown的写操作后向主动关闭方发送fin包,发送之后进入LAST_ACK状 态;
? 主动关闭方接收到fin包并进行ack回复后进入TIME_WAIT状态,等待两个MSL后进入CLOSED状态;
? 被动关闭方在接收到ack后进入CLOSED状态
? tcp连接保活机制
? 通信两端在长时间没有数据通信的情况下,服务端会每隔一段时间,向客户端发送一个保活探测数据包 (要 求对方进行回复)。若连续多次没有收到回复,则认为连接已经断开,默认7200s,每隔75s, 9次无回复直接 断开。这些数值是可以通过设置套接字选项进行设置的。
? 连接断开对于程序的影响: recv返回0,send会触发SIGPIPE异常。
(2)可靠传输
? 保证数据有序、安全到达对端
? 可靠传输的实现细节:
? a.面向连接;
? b.通过协议中的序号和确认序号进行包序管理,实现有序传输;
? c.确认应答机制:接收方对收到的每一条数据进行确认回复;
? d.超时重传机制:发送的数据等待时间超时无回复后,认为数据丢失进行重传;
? e.通过协议字段的校验和字段来检验数据一致性,不一致则丢弃,发送重传请求;
? f.避免丢包
? 第一种情况:发送方发送数据过快,过多,导致接收方接收缓冲区满溢进而丢包
? 解决方案:通过滑动窗口机制,进行流量控制;
? 此处有三种协议:停等协议,回退n步协议,选择重传协议
? 停等协议:收到确认回复后才会发送下一条
? 回退n步协议:从丢失的数据开始重新进行传输
? 选择重传协议:哪条数据丢失重传哪条数据
? 第二种情况:传输过程中,网络状态突然不好,导致大量丢包重传
? 解决方案:拥塞机制,以慢启动快增长的形式进行传输
? 拥塞机制的实现原理:
? 发送方维护一个拥塞窗口,用于限制当前所能发送的数据大小,而这个拥塞窗口以指数层级增长, 实现网络探测,防止传输过程中网络状态突然变差继续大量发送导致的大量丢包
? g.性能的提升:避免无谓的性能损失
? 确认序号:
? 告诉发送方确认序号之前的所有数据都已经接收成功,避免因为中间的某个中间的确认回复丢失
? 导致重传。
? 快速重传机制,减少超时等待时间:
? 接受方在接收数据时,先接收到了后发的数据,则认为前边的数据有可能丢失,连续间隔发送三条前边 数据的重传请求(确认序号是丢失的数据的起始序号)。发送方收到连续三条重传请求,则对对应确认 序号的数据进行重传。之所以发送三次重传请求时为了防止延迟到达的情况。
? 延迟应答机制:接收方接收到数据后,延迟确认回复
? 接收方接收数据后如果立即进行回复,大概率窗口都会变小,延迟应答是为了在延迟期间尽可能让上层 将数据取出,保证窗口大小和传输吞吐量
? 捎带应答机制
? 将确认回复的信息,放到将要发送的数据报头中,捎带一块传输给对方,尽可能减少纯报头的确认回复
? (一个报头至少20字节)
(3)面向字节流
? tcp的传输方式是一种基于连接的、可靠的、有序的、双向的字节流(以字节为单位)的传输方式
? tcp将要发送的数据放到发送缓冲区中,通信时从缓冲区取出合适大小的数据(不大于mss大小),封装头部进行 发送;
? tcp不限制上层的发送和接收数据的大小,数据会在缓冲区堆积,这样的好处是传输比较灵活,坏处是会产生 粘包问题(将多条数据当作一条进行处理,无法分辨数据边界)。
? tcp粘包的本质原因是tcp并不维护数据边界,
? 解决方案:在应用层进行数据边界管理,具体的技术有特殊字符、数据定长、应用层头部附加数据长度字 段
? 注意udp不会产生粘包问题
五.面试高频考察点
1.tcp为什么握手是三次,而挥手是四次?
三次握手的原因:
tcp是全双工通信,两端都必须确认对方是否具有数据收发的能力,而握手两次不安全,四次没必要;
四次挥手的原因:
fin包只能表示对方不再发送数据,不代表对方不再接收数据,被动关闭方可能还会继续发送数据,因此这种情况下不能直接发送fin包,把fin包和ack一起发送给主动关闭方,而是等待上层用户不再发送数据了,调用close或者shutdown的写操作后才会发送fin包。
2.tcp三次握手失败后,通信两端会如何处理?
? 客户端会连续发送syn请求;
? 服务端回复ack和syn之后,如果超时得不到ack回复,则会发送rst重置连接报文,然后释放新建套接字;
3.TIME_WAIT的作用?
? TIME_WAIT是主动关闭方在断开连接过程中进行最后一次ack回复后进入的状态。
? TIME_WAIT在等待两个msl时间之后释放资源,等待两个msl是为了保证能够对重传的fin进行处理,以及保证本 次通信的所有数据都消失在网络中,从而不会对新的连接造成影响。
具体细节:
如果主动关闭方回复最后一次ack后直接释放资源,就有可能在新的客户端中使用原来的这个地址信息,而如果上次ack丢失的情况下会重传fin,则新客户端收到重传的fin对新连接造成影响,以及发送syn也会受到影响。
time_wait更多的是为了保护客户端启动不会使用刚关闭的套接字地址信息信息,而受到上个套接字的通信遗留问题影响。
4.一台主机上出现大量的time_wait是什么原因?如何解决?
? time_wait是主动关闭方在断开连接过程中进行最后一次ack回复后进入的状态。
? 因此一台主机出现大量的time_wait意味着主动关闭了大量的套接字。
? 解决方案:
? 1.减少time_wait时间;
? 2.使用套接字选项setsockopt进行地址复用;
int setsockopt(int sockfd, int level, int optname,
const void *optval, socklen_t optlen);
5.一台主机上出现了大量的CLOSE_WAIT是什么原因?如何解决?
? close wait是被动关闭方,在收到fin包进行ack回复之后所进入的状态.
? 这个状态是等待上层用户层调用close/shutdown(wr)后发送fin包的一个状态,如果主机上出现了大量的
? close_wait的连接,那么意味着可能在代码中没有关闭套接字。
6.tcp如何实现可靠传输?
1.可靠传输:面向连接,包序管理,确认应答,超时重传,校验和;
2.避免丟包:滑动窗口,拥塞机制;
3.提高性能:延迟应答,捎带应答,延迟发送。
7.udp如何实现可靠传输?
? 在应用层通过tcp实现可靠传输的机制来实现
|