TCP是面向连接、可靠的、基于字节流的传输层通信协议
面向连接:一对一连接,不像UDP可一对多
可靠的:无论网络链路出现了什么样的变化,TCP都可保证一个报文一定能到达接受端
字节流:消息无边界,且按序交给应用层处理,会对重复报文自动丢弃
TCP和UDP的区别
(1)首部字节:TCP 20~60字节 UDP 8个字节
(2)UDP不提供复杂的控制机制,利用IP提供面向无连接的通信服务,即刻传输数据
(3)TCP是一对一,UDP支持一对多,多对多的交互通信
(4) TCP是可靠交付数据,数据无差错、不丢失、不重复,按需到达
UDP是尽最大努力交付,不保证可靠交付数据
(5)TCP由拥塞控制和流量控制,保证数据传输的安全性,UDP无,即使网络堵塞,其发送速率也不会改变
(6)传输方式:TCP流式传输,无边界,但保证顺序和可靠,
UDP一个包一个包的发送,有边界,但可能丢包或者乱序
TCP用于保证数据的可靠交付:FTP文件输出,HTTP/HTTPS
UDP面向无连接,处理简单高效,视频,音频等
三次握手:
1:客户端会随机初始化序列号,同时把SYN位置为1,接着把报文发送给服务端,标识向服务端发起连接
2:服务端收到客户端的SYN报文后,也会首先随机生成一个序列号,把确认应答号处填客户端Syn报文的序列号+1
接着把SYN ACK标志位置1,把该报文发送给客户端
3:客户端接受报文后,向服务端回应最后一个报文。将ACK标志位置为1,确认应答号为服务端发送来的报文序列号+1,并发送该报文
为何三次握手不能两次
1、防止历史连接初始化了连接,旧的SYN报文比最新的SYN报文先到达服务端,那么服务端做出响应后,
客户端能感知这是个历史连接(序列号过期或者超时),那么客户端会发送RST给服务端,终止这一次连接。
2、序列号很重要,它需要这样的一来一回(客户端发送SYN 服务端响应确认应答号,
服务端响应SYN客户端响应)来确保双方的序列号能被可靠同步,因为序列号很关键。
(通过序列号去重、按序接受、标记的哪些被接受)
四次挥手
双方都可以主动断开TCP连接,断开后主机中的资源将被释放
1、客户端打算关闭连接。会发送一个TCP首部FIN标志为1的报文,FIN报文,之后客户端进入FIN_WAIT_1状态
2、服务端接受后响应ACK,进入CLOSED_WAIT状态
3、客户端接受后,进入FIN_WAIT_2状态
4、服务端处理完数据后,向客户端发送FIN报文,之后进入LAST_ACK
5、客户端接受FIN,回应ACK,进入TIME_WAIT
6、服务端接受ACK后,进入closed状态,客户端在经过2MSL后,自动进入closed。
为啥有TIME_WAIT状态
主动发起关闭连接的一方,才有这种状态
(1)防止旧连接的数据包:
假设有的数据包在连接关闭时因为网络延迟耽搁了,若TIME状态太短或者无,
那么下次相同端口的TCP连接被复用后,延迟的数据包抵达了客户端,
接受这个过期的报文,会造成数据错乱
(2)保证连接正确关闭
如果客户端最后一个ACK丢失了,无TIME或者过短,就close,那么服务端会一直处于LAST_ACK状态
2MSL
MSL指报文最大生存时间,任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。
Time_wait等待2倍的原因:数据包由发送方发送,接收方接受后又会向对方发送响应,一来一回需要等待2倍的时间。Linux中2MSL默认是60s
MTU和MSS
MTU:一个网络包的最大长度,以太网中一般未1500个字节
MSS:除去IP和TCP头部之后,一个网络包所能容纳的TCP数据的最大长度
当IP层有一个超过MTU大小的数据,那么IP就要进行分片,保证每个分片都小于MTU。进行分片后,由目标主机的IP层进行重新组装后,再交给上一层TCP传输层。
有隐患:如果IP分片丢失,整个IP报文的所有分片都得重传。
IP无超时重传机制,由TCP来负责超时和重传,接收方发现TCP某一片丢失,不会响应ACK给对方,
发送方的TCP在超时后,才重传整个TCP报文(头部+数据),效率低下。
因此,为了提升传输性能,TCP协议在建立连接的时候通常要协商双方的MSS值,当发现数据超过MSS时,
则就会进行分片,分片后形成的IP包不会大于MTU,IP也不用分片,经过TCP分片后,TCP分片丢失,
重发时也是以MSS为单位,大大增加了重传的效率。
SYN攻击
攻击者短时间内伪造不同IP地址的SYN报文,服务端每接受到一个SYN,则进入SYN_RCVD,但是其发送的SYN+ACK无法得到响应,久而久之就会占满服务端的SYN接受队列,使得服务器不能为正常用户服务
解决方式:修改Linux内核参数,控制队列大小和当队列满时应做什么处理