有链接,无连接,可靠协议 不可靠 有状态 无状态区别
- 不可靠: 不能保证数据安全准确的传输给对方 提供尽力而为的的交互服务。
- 可靠:保证数据安全准确的传输给对方。
- 有链接: 数据发送方与数据接收方需要简历对话并维持该链接
- 无连接: 数据发送方与数据接收方不需要建立对话并维持该链接。
- 有状态:对于事物处理拥有记忆能力 对于之前处理过的事务保留其信息。
- 无状态: 对于事务没有记忆能力 对于之前处理过的事务不在保留其信息。
简述HTTP协议
- HTTP(超文本传输协议) 是应用层上的一种基于c/s架构的无连接无状态的请求/响应模式通信协议。
- HTTP有请求报文和响应报文两种形式。
请求报文由四个部分组成:
请求行 + 请求头 + 空行+ 请求体
- 请求行
1.1 请求方法
GET:重点在于从服务器上获取资源。
POST: 重点在于向服务器发送数据(例如提交表单或上传文件)
HEAD: 类似于GET请求,不过返回的响应报文中没有响应体承载数据,只用于获取响应报头。
1.3 协议版本
有HTTP1.0 , HTTP1.1, HTTPS 等协议
- 请求头
通过键值对的方式存储。常见的如Content-Type(请求体/响应体的类型),Content-Length(请求体/响应体的长度),Content-Encoding(请求体/响应体的编码格式)
- 空行
用于区分请求体
- 请求体
用于存放实际的数据
- 响应报文
响应报文同样分为四个部分: 状态行 + 响应头 + 空行 + 响应体
- 状态行
1.1 协议版本
一般跟请求报文对应的协议版本相同,有HTTP1.0,HTTP1.1,HTTPS。
1.2 状态码
HTTP状态码有五种类型,如下:
1**:信息,服务器收到请求,要求请求者继续操作;
2**:成功,操作成功接收并处理;200 OK:客户端请求成功;
3**:重定向,需要进一步的操作以完成请求;301:网页被永久转移到其他URL;302:网页临时跳转。
4**:客户端错误,请求包含语法错误或无法完成请求;400 Bad Request:客户端请求有语法错误,不能被服务器所理解;401 Unauthorized:请求未经授权;404:请求资源不存在,可能输入了错误的URL。
5**:服务器错误,服务器在处理请求的过程中发生了错误。500:服务器内部发生了不可预期的错误;503 Server Unavailable:服务器当前不能处理客户端的请求。
GET和POST有什么区别?
- GET重点在从服务器获取数据;POST重点在于向服务器发送数据。
- GET和POST都能够使用额外的参数,GET的参数出现在URL之中并用
?隔开,参数之间用&相连,是可见的;POST提交的数据是放在请求体中,是不可见的。 - GET传输数据时会有安全问题,在提交数据时用户名和密码都会出现在URL上面,黑客可以轻松获得;而POST方法提交的数据由于是存放在请求体中,不会被显示。
- GET传输数据大小有限制(因为浏览器对URL长度有限制);POST方法传输的数据没有限制。
301和302状态码的区别?
- 301(Moved Permanently)状态码代表网页被永久转移到其他URL;302(Found)状态码代表网页被暂时转移到其他URL。
从输入URL到页面加载发生了什么?(HTTP的工作原理?)
- 浏览器向
DNS(Domain Name Server)请求,DNS将域名转换为对应的IP地址。 - 浏览器连接到Web服务器
HTTP/80端口,三次握手创建TCP连接。 - 浏览器发送HTTP请求,读取URL域名后面对应文件,并注意该请求作为TCP三次握手中的第三次握手的数据发送给Web服务器。
- 服务器接收HTTP请求并返回HTTP响应,响应体中存放对应的
html文本。 - 如果CONNECITON模式为
close, 立刻四次挥手释放TCP连接;若CONNECTION模式为keep-alive,则保持该连接一段时间后再释放,这段时间内还可以接受请求。 - 浏览器解析
html文本内容并显示。
HTTP长连接和短连接的区别?
- 长连接 CONNECTION字段设置为
keep-alive,在建立连接,传输数据之后,并不会马上断开连接,而是等待一段时间之后再断开,这段时间可以再多次传输数据。 - 短连接 CONNECTION字段设置为
closed,在建立连接,传输数据之后,立刻断开连接。会有较大的开销。
补充: 1.HTTP1.0默认使用短连接,HTTP1.1默认使用长连接。 2.长连接分为流水线方式和非流水线方式,非流水线方式就是在接收到HTTP的下一次响应之前都不能再发送新的请求报文,流水线方式就是在接收到HTTP下一次响应报文之前都可以发送新的请求报文。
HTTP是不保存状态的协议,那么如何保存用户的状态?(Cookie,Session的区别是什么?)
使用Cookie 和Session。
- Session
Session存储在服务器中,会为每一个用户都创建特定的sessionID并且保存对应数据,数据可以保存在内存或数据库中。
- Cookie
Cookie存储在客户端浏览器中,会记录下该浏览器对应的SessionID,并且 每一次HTTP请求都会把SessionID发过来,这样服务器就能识别该用户了;同样cookie也可以用来记录用户的信息,比如账户密码等。
如果Cookie被禁用怎么办?
可将URL重写,也就是将SessionID直接附加在URL路径的后面。
HTTP1.0 和 HTTP1.1的主要区别是什么?
- 长短连接:HTTP1.0默认使用短连接;HTTP1.1默认使用长连接。
- 错误状态响应码:HTTP1.1中新增了24个错误状态响应码。
- 缓存控制策略:HTTP1.1中请求头中引入了更多的缓存控制策略。
- 断点续传功能:HTTP1.1中请求头中引入了range,可以只请求资源的某个部分,实现断点续传。
URI和URL的区别是什么?
- URI 统一资源标识符(Uniform Resource Identifier),在某一种规则下能唯一的标识出一个资源。
- URL 统一资源定位符(Uniform Resource Location),用定位的方式唯一的标识出一个资源。
URL就是用定位方式实现的URI。
TCP协议是什么?
TCP协议是一个面向连接的,可靠的,基于字节流的全双工端对端通信协议。
面向连接的意味着数据发送方与数据接收方需要建立对话并维持该来连接。 可靠的意味着能保证数据安全准确的传输给对方。 基于字节流意味应用程序对于数据的发送和接收都是没有边界限制的。
补充:TCP基于字节流/UDP基于数据报的理解,TCP传输的send/recv函数,UDP的sendto/recvfrom函数。
简述TCP头部结构?
- 第一行
源端口号(16bit) + 目的端口号(16bit) : 端口号用于区分同一个IP地址下的不同应用程序。我们将 IP + Port 称为一个插口(Socket)。设立端口号的原因是同一个IP下可能运行了多个应用程序,如FTP(21),SMTP(25),SSH(22)等。
- 第二行
序列号(32bit) : 英文为seq,序列号的作用有两点,一是保证数据包的传输顺序,二是避免因网络延迟带来的网络混乱;客户端向服务器发送的序列号一般为ISN(initial sequence number) + 1;SYN和FIN会消耗掉一个序列号。
- 第三行
确认号(32bit) : 英文为ack,假设收到了ISN 为x的SYN报文,那么ack值就应该为x+1,代表已经收到了该报文。
- 第四行
头部长度(4bit) :最小为20字节(0101),最大为60字节(1111) 保留(6bit) 标志位(6bit) : URG:紧急标志 ACK:确认标志,代表确认号是否有效 PSH:提示接收端应用程序应该立刻从TCP缓冲区读走数据,为后续接收数据腾出空间。 RST:复位报文段,要求重新建立连接 SYN:同步报文段,请求建立连接 FIN:结束报文段,通知对方本方将要关闭连接 窗口大小(16bit) :英文名 window size,也可以称为滑动窗口,是TCP流量控制的手段,用于告诉对方TCP接收缓冲区还能够接收多少字节的数据,这样对方可以控制发送数据的速度。窗口大小实质上对应了内核socket接收缓冲区的大小。
- 第五行
校验和(16bit) :使用CRC算法检验TCP报文段 头部 + 数据 部分是否有损坏,保证了TCP的可靠传输。 紧急指针(16bit) :紧急指针相对当前序列号的偏移,URG置位1时才有效,目前已弃用,不做过多了解。
简述TCP三次握手与四次挥手?
- 三次握手
开始时客户端和服务器均处于 CLOSED 状态,在socket编程中,服务器 listen() 之后被动打开,客户端 connection() 之后主动打开,之后进行三次握手:
- 第一次握手
客户端给服务器发送SYN报文,并指明客户端的ISN,此时客户端处于SYN-SENT状态。
TCP报文头部 SYN = 1 , seq = x。
- 第二次握手
服务器收到了客户端的SYN报文之后,会发送自己的SYN-ACK报文作为应答,在报文中指明了自己的ISN;此时服务器处于SYN-RCVD 状态。
TCP报文头部 SYN = 1, ACK = 1,seq = y, ack = x + 1。
- 第三次握手
客户端接收到服务器的SYN之后,发送ACK报文作为应答发送后客户端进入 ESTABLISHED 状态,服务器收到ACK后也进入 ESTABLISHED 状态,双方开始数据交换。
TCP报文头部 ACK = 1, seq = x + 1,ack = y + 1。
- 四次挥手
开始时客户端和服务端都处于ESTABLISHED状态,假设客户端先发起关闭请求进行主动关闭,服务端接收到通知后,进行被动关闭。 在网络编程中,任意一方执行 close()操作,都会执行四次挥手。
- 第一次挥手
客户端向服务端发送FIN报文,同时指定自己的序列号,此时客户端处于 FIN-WAIT1 状态。
TCP报文头部信息:FIN = 1,seq = u。
- 第二次挥手
服务端接收到客户端的FIN报文后,发送ACK报文作为应答,服务端处于 CLOSE-WAIT 状态,客户端收到ACK后处于FIN-WAIT2状态,此时TCP处于半关闭状态,服务端仍然在向客户端发送数据。
TCP报文头部信息:ACK = 1,seq = v,ack = u + 1。
- 第三次挥手
服务端发送完数据之后,向客户端发送 FIN-ACK报文,此时服务端处于 LAST-ACK 状态。
TCP报文头部信息:FIN = 1, ACK = 1,seq = w,ack = u + 1。
- 第四次挥手
客户端接收到服务端的FIN-ACK报文后,发送ACK报文给客户端,此时客户端处于 TIME-WAIT 状态,需要等待 2MSL,之后进入CLOSED状态,服务端接收到ACK后也进入CLOSED状态。
TCP报文头部信息:ACK = 1,seq = u + 1, ack = w + 1。
补充: SYN报文会消耗序列号,不能携带数据。 FIN报文会消耗序列号,不能携带数据。 ACK报文如果携带数据则会消耗序列号,如果不携带数据则不会消耗序列号。
为什么要三次握手?只有两次握手可以吗?
三次握手才能保证双方的接收发送能力都是正常的,第三次握手有两点作用:
- 客户端的SYN报文因网络延时后滞后,此时客户端超时重传SYN报文并与服务器已经完成了数据的传输,随后第一次的SYN报文之后到达服务器,服务器误认为这是一次新的连接请求,于是发送SYN-ACK给客户端,并直接进入ESTABLISHED状态,但是客户端会直接忽略这一次SYN-ACK,导致死锁。
- 如果第二次握手的ACK信号丢失,服务器直接进入ESTABLISHED状态,而客户端没有收到ACK信号,还处于SYN-SEND阶段,则会形成死锁。
三次握手过程中可以携带数据吗?
第一次第二次握手不行,第三次握手可以;
假如第一次握手可以携带数据,那么如果有人要恶意攻击服务器,会在SYN报文中存入大量数据,并疯狂发送SYN报文,服务器将会因处理这些报文陷入瘫痪。
第三次握手返回ACK报文时,双方连接已经建立,自然可以携带数据。
为什么连接的时候是三次握手,关闭的时候却是四次挥手?(为什么挥手需要四次,三次挥手不行吗?)
挥手必须四次,因为四次挥手中,服务器收到FIN后,并不能立刻返回FIN-ACK,而是先发送ACK,也这是为什么挥手需要四次的原因,因为需要等到数据传输完成才行,再发送FIN-ACK,这两个不能合到一起发送,所以需要四次挥手来关闭连接。
为什么客户端需要等待2MSL再关闭?
原因有两点:
- 保证客户端最后发送的ACK能够到达客户端 如果这个ACK报文丢失,服务器超时重传FIN-ACK,客户端在2MSL的时间内一定可以接收到这个超时重传的FIN-ACK,这样可以避免服务器没有收到最后的ACK而空等待。
- 防止旧连接中的报文影响新连接 客户端在发送最后一个ACK后,等待2MSL,这样该连接中的所有报文都已经在网络中消失,不会影响到下一个新的连接。
什么是半连接队列?什么是全连接队列?
- 半连接状态
半连接状态也就是服务器在进行第二次握手之后进入SYN-REVD的状态,并且这些连接由半连接队列存放。
- 全连接状态
全连接状态也就是完成了三次握手的连接,全连接队列将存放这些连接。
ISN是什么?是固定的吗?
ISN是TCP三次握手中为了建立连接而使用的一个初始序列号,ISN随时间而变化(每4ms加1),因此每一个连接都有不同的ISN。
ISN不固定有两个好处:
- 如果ISN固定,上一次连接的报文因网络延迟在这一次连接中到达,并恰好两次的seq相同,那么就会发生网络混乱。
- 固定ISN容易遭受到黑客攻击,黑客能得知服务器的ISN,能在第三次握手正确的返回ACK报文,与服务器建立连接。
SYN攻击是什么?(泛洪攻击是什么?)
黑客伪造大量不存在的IP地址,并不断向Server发送SYN请求,由于IP地址不存在,Server会不断发送SYN-ACK报文直至超时,这些伪造的SYN报文将导致半连接队列满,导致正常的SYN请求因无法加入半连接队列而被丢弃,这样会造成服务器瘫痪。
常见的防御SYN攻击的方法有:
1.过滤网关防护 :如设置SYN代理,让代理为服务器处理SYN请求,如果收到了客户端的ACK包那么就向服务器完成三次握手。
2.增大半连接队列容量
3.缩短超时时间与减少重传次数
4.SYNcookies技术
如果已经建立了连接,但是客户端突然出现故障了怎么办?
服务端会有一个Keep-Alive心跳包机制,也就是定期内会通过发送数据包检测客户端是否正常运行,那么就认为客户端已经出现故障, 服务器自动断开。
为什么会发生TCP粘包拆包?如何处理?
TCP粘包发生的原理是TCP传输是基于字节流的,发送端发送数据与接收端接收数据并没有边界,没有边界导致所有的数据粘合在了一起,也就发生了TCP粘包。 在socket编程中,假设发送方执行send操作x次,都只是将x次的数据发送到发送缓冲区中,真正发送到对端是由TCP协议来完成;而接受方执行recv操作y次之后将数据读取出来,并不是发送一次就对应着接受一次。
- TCP粘包发生的原因
- TCP发送缓冲区的数据堆积了很多之后才发送;
- TCP接收缓冲区的数据堆积了很多之后才接收;
- TCP拆包发生的原因
- 待发送的数据部分大于MSS,需要进行拆分;
- 待发送的数据部分大于发送缓冲区剩余空间大小,需要进行拆分。
- TCP粘包拆包的处理方法 通常使用
自定义私有协议的方式来解决,协议可以按照以下方式设计:
- 发送端发送数据时添加包头部,包头部中包含数据部分的大小,再发送数据部分;接收端先接受到包头部,确定了数据部分的大小之后再读取数据部分即可进行拆包。
- 发送端发送数据时将数据包封装为固定长度,不够的用0补齐;接收端每一次接受固定长度的包即可进行拆包。
- 设置消息边界,一般使用 ‘\n’ 作为边界。