目录
tcp协议与udp协议是传输层的协议,工作目标是在程序之间进行数据传输;
- tcp是面向连接的、全双工的
- udp是面向非连接的
建立连接-三次握手
- [1]客户端主动发起请求-> 向服务端发送SYN标志(表示连接请求的数据包)表示要建立连接;
- [2]服务端接收到数据包后->向客户端发送SYN标志+ACK(表示确认数据包)标志表示可以建立连接请求;
- [3]客户端接收到数据包后->向服务端发送ACK标志建立连接;
为什么是三次握手而不是两次握手?
前提:客户端设置了超时时间,当客户端向服务端发起请求时,若是超过规定时间没有接收到服务端返回的确认请求标志,那么客户端会重新发起一个新的请求;
1.为了防止已失效的请求报文突然又传送到服务器引起错误,造成资源浪费。
若是仅有两次握手,可能会出现下述状况:
- 客户端发起 请求1->SYN,但是由于网络等原因没有发送到服务端;
- 客户端长时间没有接收到服务器的响应,超时之后->重新发起请求2 ->SYN;
- 服务端成功接收到请求2并返回确认->SYN+ACK,建立连接可传输数据;
- 但是此时客户端收到了 请求1(已废弃);
- 此时客户端认为建立了1个连接,但是服务端认为建立了两个连接;
- 无法确认连接的是否为历史连接,容易造成错误;
- 若是这样的情况很多,服务端会建立很多无效连接,造成资源浪费;
发送数据
在使用tcp协议传送数据的过程中,会将数据分隔为一块一块的数据包,但是这样会产生两个问题
- 丢包问题
- 乱序问题
如何解决-保证数据的完整性的呢?
在发送数据之前会将数据存在 发送缓冲区(标记序列) 从建立连接后的第一个字节的序列号为0,后面的每一个字节依次增加1;
在发送数据时会将部分数据组成数据包,在tcp请求头中附带 序列号及长度;
发送数据
- 分条发送: 接收方在接收到数据之后通过 序列号以及长度将数据进行拼接,并恢复确认 ACK=序列号+长度=下一包数据的起始序列号;
- 若是接收数据不一致->发生丢包时,可以要求发送方进行重传;
- 一次发送多个数据包:接收方在接收到数据之后通过 序列号以及长度将数据进行拼接为完整数据,仅需回复一次确认即可 ACK;
- 若是接收数据不一致->发生丢包时,可以要求发送方进行重传;
四次挥手
处于连接状态的客户端与服务端都可以发送断开连接请求;
- [1]客户端主动发起请求->发送FIN(表示关闭连接的数据包)标志,表示要关闭连接;
- [2] 服务端表示确认->回复ACK(表示确认的数据包)标志,表示知道客户端要关闭连接了;但是此时服务端还是可以发送数据的
- [3]当服务端数据发送完毕,发送FIN(表示关闭连接的数据包)标志,表示要关闭连接;
- [4]客户端发送确认ACK,并进入等待超时时间,超时后关闭,服务端收到ACK后进入关闭状态;
客户端为什么存在等待超时时间
因为客户端发送 ACK数据包后,若是因为某种原因导致数据包没有被服务端成功接收,那么服务端会重新发送FIN数据包表示关闭连接请求。此时若是客户端已经关闭连接了,那么服务端的此条连接会一直处于等待状态,造成资源浪费。此时客户端处于等待超时状态,若是接收到新的FIN,会重新发送ACK包,刷新超时等待时间至超时自动关闭。