协议
概念

TCP/IP协议组
概念
TCP/IP协议(Transfer Controln Protocol/Internet Protocol)叫做传输控制/网际协议,又叫网络通讯协议,这个协议是Internet国际互联网络的基础。
底层原理
我们先看一张图:

由上图我们可以看到,我们的发送端,将数据通过应用层、传输层、网络层、链路层发送到接收端,每经过一层,会包裹一个首部。而接收端解析的过程则是正相反,是每解析一层,便删除一个首部,直到获取到传输的数据。
我们日常工作中,最常接触的就是TCP协议,和UDP协议。下文将分别介绍这两种协议。
TCP
概念
传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。
TCP FLAGS
我们都知道,TCP的连接与断开是要经过三次握手和四次挥手的。那么,在我们正式介绍这两个流程之前,我们先要了解一下TCP FLAGS。参考下图:

由上图我们可以看到,TCP的指针类型一共分为六种。我们重点关注标红的指针内容。这些内容,在TCP的连接以及断开的过程中,存在于报文头部,来向发送端与接收端传递通讯有效的标识等内容。如果有兴趣的话,我们可以通过抓包工具,抓一下HTTP请求的包,里面就可以看到一个TCP建立连接以及断开的全过程以及在这个过程中两端的报文头数据。
三次握手
TCP的连接需要三次握手才可以建立。说是三次握手没其实是一个比喻,实际上就是进行三次报文发送,如下图所示:

- 第一次握手:客户端主动打开一个连接,向服务端发送一个SYN的包,将一个初始化的seq发送给服务端,自己进入SYN-SENT的状态。
- 第二次握手:服务端接受到客户端的SYN包之后,确认客户端的SYN(ack=x+1),初始化一个seq,回送一个SYN包(seq=y)和ACK包。自己进入SYN-RCVD的状态。
- 第三次握手:客户端接受到SYN包和ACK包,解析ACK包的数据,确认服务端正常,并回送一个ACK包(ack=y+1)给服务端。自己进入ESTAB-LISHED状态。同时,服务端接受到ACK包并解析确认后,也进入ESTAB-LISHED状态,连接建立成功。
整个握手的过程,通俗一点讲,就是由客户端发起连接,双发均发送同步序号(SYN)包,双方收到后,均回送一个确认序号(ACK)包,双方解析验证ACK包无误之后,连接建立成功。这个过程结束之后,也就初始化好了这个连接的序列号,为了之后的数据传输做好了准备。
三次握手的一些问题
SYN超时
起因
服务端接受到客户端的SYN,回送SYN-ACK之后未收到客户端的ACK回执。这种情况下,服务端会不断重试,直到超时才断开连接(Linux默认63秒断开连接:因为Linux系统会默认重新发送确认报文5次,每次的间隔时间都翻倍,所以间隔时间为1s 2s 4s 8s 16s,之后在等待32s的时间才会断开连接,加起来就是63s)。针对这种情况,如果有人恶意的向服务器不断的发送SYN,发送之后就下线,服务器会超时之后才关闭连接。这样的话,很容易将服务器的连接队列占满,从而导致正常的连接连接失败。这种攻击方式称之为SYN Flood。
解决方案(LINUX)
在SYN队列满后,再接收到SYN请求,会直接回发tcp_syncookies的参数,客户端接受到参数后回发SYN Cookie(服务器通过源地址端口和目标地址端口还有时间戳打造出的一个特定的序列号),服务端会直接建立连接。
建立连接后,Client出现故障怎么办
起因
连接成功建立,之后Client出现故障,此时连接应该是无效连接,应该释放资源。
解决方案(LINUX)
连接建立之后,向对方发送探测报文,如果未收到响应,则会继续发送,直至到设置的尝试次数,便断开连接,这种方式我们称之为保活机制。保活机制是连接端的主动行为,启动保活机制的一端才会有此行为。
四次挥手
上面我们解释了连接的建立过程,这一小节我们介绍一下连接的断开,也就是所谓的四次挥手。请参考下图:

- 第一次挥手:客户端向服务端发送FIN包,并附带当前的序列号seq。也就是向服务端发送断开连接的信号。同时,将自己的状态置为FIN-WAIT-1。
- 第二次挥手:服务端接收到FIN包并解析(ack=u+1),回送一个ACK包并附带自己的序列号seq, 会将自己的状态置为CLOSE-WAIT。等它将自己的数据发送完毕时,会向客户端发送一个FIN包,并附带当前的序列号seq,同时将自己的状态置为LAST-ACK。
- 第三次挥手:客户端接收到服务端的ACK回执,解析确认之后将自己的状态置为FIN-WAIT-2。同时,接收到服务端的FIN包,解析确认之后(seq=u+1),回送一个ACK给服务端,将自己的状态重置为TIME-WAIT。之后,会等待2个MSL(Linux的MSL规定的为30s)的时间,关闭客户端。
- 第四次挥手:服务端接受到客户端的ACK包,解析确认之后,将连接关闭。
注意:本图只是演示了客户端主动发起关闭。关闭连接的操作,双方都可以主动发起,服务端主动发起断开连接的请求流程都相同,只不过状态会互换。
四次挥手的一些问题
为什么要设置TIME-WAIT状态
设置这个状态并等待的原因是客户端要确保有足够的时间让对方接收到ACK回执的包。因为我们如果给被动关闭的一端发送了ACK回执,但是回执丢失,我们要确保主动关闭的一端有足够的时间来正确处理被动关闭端发来的重试FIN。还有一个原因就是防止新旧连接的冲突。简单来说,就是被动关闭的一方在收到ACK包之后会关闭连接,如果同时,在原端口发起了一次新连接,此时旧链接还处于TIME-WAIT状态,TCP会重新建立连接,而不是复用处于TIME-WAIT的旧连接。这样,就避免了新旧连接的混淆。
服务器出现大量TIME-WAIT状态的原因是什么
服务器出现这个的原因是因为对方关闭了连接,我方忙于读写等操作未及时关闭连接。一般是由于代码中忘记释放资源或者配置的线程数有问题导致。(检查网络状况的指令(Linux):netstat -n | awk '/^tcp/{++S[$NF]}END{for(a in S) print a,S[a]}')
滑动窗口
参考下图:

- LastByteAcked:连续被接收端接受并已经返回的确认序列号最大值
- LastByteSent:已发送的最后一个字节的位置(未收到ACK确认)
- LastByteWritten:上层应用已写完的最后一个字节的位置
- LastByteRead:上层应用已经读完的最后一个字节的位置
- NextByteExpected:收到发送端的连续序列号的最大值的位置,接收到但没有反馈确认ACK
- LastByteRcved:已收到的最后一个字节的位置
- MaxRcvBuffer :接收方缓存的大小(上述窗口的大小只有发送完回执才会清理掉缓存)
- AdvertisedWindow:还能够接受的窗口大小
- EffectiveWindow:还需要发送的窗口大小
UDP
概念
UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection) 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。
报文结构
参考下图:

从上图中,我们可以看到:UDP的协议头一共占8个字节,分为四个部分(源端口、目标端口、数据长度和检验数)。那么,UDP一次可以发送多少字节呢?答案是65507。因为报文一共有16位存储报文长度,所以理论上可以发送2^16-1=65535个字节长度,但是要减去20字节的IP协议头和8字节的UDP协议头,所以一共可以发送65507个字节。如果我们发送的信息长度大于改限制的话,我们需要手动分包来处理。
特点
- 面向非连接
- 不维护连接状态,支持同时向多个客户端发送相同的数据
- 报文头只有8个字节,额外的开销很小
- 吞吐量只受限于数据的生成速度、传输速率以及机器的性能
- 尽最大努力交付,不保证可靠交付,不需要维护复杂的连接状态表
- 面向报文,不对应用程序提交的报文进行拆分或者合并
和TCP的区别
- TCP是面向连接的,UDP是面向无连接的
- TCP是可靠的,UDP只能保证最大交付,并不保证可靠交付
- TCP的有序传输的,UDP是无序传输的
- TCP的速度比UDP要慢
- TCP的量级比UDP重
补充概念
- RTT:发送一个数据包到收到对方的ACK,所花费的时间
- RTO:重传的时间间隔
HTTP
概念
HTTP协议,即超文本传输协议(Hypertext transfer protocol)。是一种详细规定了浏览器和万维网(WWW = World Wide Web)服务器之间互相通信的规则,通过因特网传送万维网文档的数据传送协议。
特点
- 支持客户端/服务器模式
- 简单快速
- 灵活
- 无连接
- 无状态
请求结构
参考下图:

响应结构
参考下图:

请求/响应的步骤
- 客户端连接到WEB服务器
- 发送HTTP请求
- 服务器处理请求,返回HTTP响应
- 释放TCP连接
- 客户端浏览器解析响应内容
在浏览器输入网址,按下回车键的流程
- DNS解析域名为IP
- 建立TCP连接
- 发送HTTP请求
- 服务器处理请求,返回HTTP响应
- 浏览器解析响应内容
- 释放TCP连接
HTTP状态码
- 1XX:指示信息--表示请求已经接收,继续处理
- 2XX:成功--表示已经被成功接收、理解
- 3XX:重定向--要完成请求必须进行进一步的操作
- 4XX:客户端错误--请求有语法错误或者请求无法实现
- 5XX:服务端错误--服务器未能实现合法的请求
常见状态码:
- 200 OK :正常返回信息
- 400 Bad Request:客户端请求有语法错误,不能被服务器所理解
- 401 Unauthorized:请求未经授权,这个状态码必须和WWW-Authenticate报头域一起使用
- 403 Forbidden:服务器收到请求,但是拒绝服务
- 404 Not Found:请求资源不存在,比如输入了错误的URL等等
- 500 Internal Server Error:服务器发生不可预期的错误
- 503 Server Unavailable:服务器当前不能处理请求,一段时间后可恢复
GET和POST的区别
- Http报文层面:GET将请求信息放在URL,POST将请求星系放在请求体
- 数据库层面:GET请求符合幂等性和安全性,POST不符合
- 其他层面:GET请求可以被缓存,POST不可以
HTTPS
概念
HTTPS (基于安全套接字层的超文本传输协议 或者是 HTTP over SSL) 是一个 Netscape 开发的 Web 协议。你也可以说:HTTPS = HTTP + SSL。
什么是SSL
SSL(Security Sockets Layer,安全套接层)是为网络通信提供安全以数据完整性的一种安全协议。是操作系统对外的API,SSL3.0后更名为TLS。它会采用身份验证和数据加密保证网络通信的安全和数据完整性。
加密方式介绍
- 对称加密:加密和解密都是用同一个密钥(性能高)
- 非对称加密:加密和解密的密钥不相同(性能低)
- 哈希算法:将任意长度的值转换为固定长度的值,算法不可逆
- 数字签名:证明某个消息或者文件是某人发出/认可的
数据传输流程
- 浏览器将支持的加密算法信息发送给服务器
- 服务器选择一套浏览器支持的算法,以证书的形式回发浏览器
- 浏览器验证证书的合法性,并结合证书公钥加密信息发送给服务器
- 服务器使用私钥解密信息,验证哈希,加密响应信息回发浏览器
- 浏览器解密响应信息,并对消息进行验真,之后进行加密交互数据
HTTPS和HTTP的区别
- HTTPS需要到CA申请证书,HTTP不需要
- HTTPS是密文传输,HTTP是明文
- HTTPS默认使用443端口,HTTP默认使用80端口
- HTTPS较HTTP来讲,安全性较高
HTTPS真的安全吗
未必说网站HTTPS化之后就绝对安全,因为现在浏览器默认使用HTTP,需要手动跳转HTTPS,在跳转的过程中,有被劫持的风险。针对这种那个情况,我们可以使用HSTS(HTTP Strict Transport Security)来优化。
Cookie
概念
cookie是由服务器发送给客户端的一种特殊信息,以文本的方式存放在客户端。当客户端再次发起请求的时候,会在请求中携带Cookie一起发送给服务器。浏览器接受后会解析生成与客户端Cookie相对应的内容。
发送过程如下图所示:

Session
概念
Session是服务器端的一种机制,是在服务器上保存的信息。
实现机制
如下图:

Session有两种实现方式:使用Cookie来实现或者使用URL回写来实现。使用Cookie的方式就如上图所示,我们无需手动操作,浏览器会自动存储服务起发来的key为JSESSIONID的Cookie并在下次请求中携带。URL重写就是我们显式的把jsession作为参数key,Session的值作为value写在URL上。我们的SpringMVC框架会根据请求体自动识别。
Session和Cookie的区别
- Cookie存放在客户端上,Session存放在服务器上
- Session相对于Cookie较为安全
- 若考虑减轻服务器负担,应使用Cookie
Socket
概念
Socket是对TCP/IP的抽象,是操作系统用对外开放的接口。如下图所示:

通信流程
同新流程参考下图:

大体上讲就是分为一个服务端,一个客户端。服务端绑定到一个端口上,并持续监听连接。客户端向该服务端地址(IP+监听的端口)发起连接。连接建立成功之后,建立一个全双工的通信通道,进行双方的通信。
文章评论