TCP
TCP(Transmission Control Protocol)传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议。
目录:
TCP报头
TCP的三次握手
TCP的四次断开
SCTP协议
TCP报头
- 16Bit-源端口:用来标识计算机中不同的应用进程
- 16Bit-目标端口:接收方的应用程序接口
- 32Bit-序列号:序列号是本报文段发送数据组的第一个字节的序号,每一个字节一个序号,如果说一个报文的序列号为100,此报文的数据部分有200字节,下一个报文段的序列号就为300,序列号保证了TCP传输的有序性
- 32Bit-确认号:只有当控制位中ack=1时,该确认号才生效,它指明下一个期待收到的字节序列号,表明该序列号之前的数据已经收到
- 4Bit-头部长度:TCP的长度时不确定的,报头不包含任何选项字段长度为20byte,4Bit的头部长度是做数据偏移,指示了数据区在报文段中的起始偏移值
- 6Bit-resv:为QOS做预留,TCP排队机制
- 6Bit-控制字段
- URG:紧急指针标志,为1时表示TCP报头中紧急指针有效,为0时忽略紧急指针,没有意义
- ACK:确认序列号标志,为1时确认号有效,为0时报文中不含确认信息
- PSH:紧急数据标志,为1时表示带有紧急标志的数据,指接收方接收到该报文后,尽快交给应用程序
- RST:重新连接标志,用于重置主机崩溃,错误连接,拒绝非法的报文段,拒绝连接
- SYN:同步序号,用于建立连接的过程,在请求中,SYN=1和ACK=0表示,没有ACK确认,SYN=1和ACK=1,表示有ACK的确认
- FIN:Finish标志,用于释放TCP连接,为1时,本地没有数据发送,即将终止本地数据流
- 16Bit-滑动窗口:滑动窗口大小,用来告知发送端的cache大小,控制数据发送的速率,做流量控制,最大65535
- 16Bit-校验和:做奇偶校验,此校验和针对于整个TCP报文段,包括头部和数据
- 16Bit-指针:控制位UGR=1时,该指针生效,是一个偏移量,和序列号字段中的值相加表示紧急数据的最后一个字节的序号,用于在发送紧急数据时
- 32Bit-选项填充字段:最常见的为MSS最大段长度,每个连接方通常在第一个报文段中指出该选项,表示本端能接受的最大段长度
TCP连接的三次握手
- 第一次握手: 客户端发出连接请求消息到服务端,SYN(SEQ=x)报文给服务器端,进入SYN_SEND状态
- 服务端:此时服务端收到客户端的SYN,服务端知道自己与客户端是可以连接成功的
- 客户端:此时客户端并不知道服务端是否收到自己的请求连接消息->第二次握手
- 第二次握手: 第二次握手是服务端发出确认包ACK,来确认收到客户端的请求连接消息,SYN(SEQ=y)ACK(ACK=x+1),服务端进入SYN_RECV状态
- 第三次握手: 客户端收到服务端的SYN报文,回应一个ACK(ACK=y+1)报文,进入Established状态,服务器接收到客户端的ACK,进入Established状态
第一次是发出请求,第二次是应答,只有当客户端确定了自己能与服务端连接上才能开始收发数据,服务端只有收到客户端的请求才能进行信息的传递,这是最基本的
第三次是为了防止已经失效的连接请求报文突然又传到服务端(由于网络卡顿的原因),当服务端再次收到SYN时,会认为客户端没有收到自己的ACK+SYN,会再次发送ACK+SYN,回造成资源的浪费,所以第三次是很有必要的,是客户端对服务端的再次确认。
TCP的可靠的传输控制协议,三次握手能保证数据可靠,又能提高传输效率
TCP为什么要三次握手?
-
为什么不是两次握手?
首先客户端与服务端建立TCP连接,客户端发出请求,服务端进行应答,这已经是两次握手了,如果通过这两次握手就直接连接TCP连接的话,会存在以下问题
当网络卡顿时,客户端发送给服务端的SYN报文延迟发送时,客户端没有收到服务端的ACK报文,此时会认为没有收到,客户端重新发出SYN报文,服务端回复ACK,TCP建立连接完成,但是之后客户端延迟的SYN报文会再次到达服务端,服务端会再次回复一个ACK,又建立一次连接
当服务端发送的ACK报文,由于网络原因,不能到达客户端,但是服务端会认为已经建立TCP连接,进入就绪状态等待数据传输,此时客户端没有收到服务端的ACK报文,会再次发送SYN,但是此时服务端已经进入就绪状态,那么服务端会断开连接,重新再去发送ACK报文,与客户端重新建立连接
-
为什么不是四次握手?
如果是4次握手的话,会通过以下的方式:
第一次握手: 客户端给服务端发送SYN同步报文。
第二次握手: 服务端收到SYN后,给客户端回复ACK确认报文。
第三次握手: 服务端给客户端发送SYN同步报文。
第四次握手: 客户端给服务端发送ACK确认报文。SYN和ACK只是TCP报头中的一个标识位,所以SYN和ACK可以在一个报头中定义,也就是说,第二步服务端的ACK,和第三步的ACK可以合为一步,SYN+ACK发送给客户端,这样就省了一步,提高效率
TCP连接的四次断开
是TCP的半关闭造成的,客户端和服务端都要进行关闭,才能彻底断开连接。
- 第一次挥手: 第一次挥手是客户端完成数据传送后,要与服务端断开TCP连接,此时会发送一个FIN报文,向服务端请求断开连接
- 第二次挥手: 第二次挥手是服务端收到客户端的FIN请求断开报文后,对客户端的请求的确认,向客户端发送ACK报文,表明自己已经收到客户端的消息
- 第三次挥手: 此时服务端知道客户端已经不会主动发送数据过来了,但是服务端自己还能主动发送消息,如果服务端此时没有数据要向客户端发送,会向客户端发送FIN请求报文,表明自己也要断开连接
- 第四次挥手: 第四次挥手是客户端对服务端FIN请求断开报文的确认,客户端向服务端进行确认,表名自己受到服务端的消息,此时四次挥手完毕,彻底断开连接
TCP是全双工的,客户端和服务端都可以向对象发送消息,所以断开需要双方都要发出请求,请求之后双方都要进行确认
SCTP协议
SCTP(Stream Control Transmission Protocol)是一种传输层的协议,与TCP/IP协议栈中与TCP和UDP类似,兼有两者特征
SCTP特性
SCTP是后来引入的一种新的协议,提供了和TCP一样的可靠、有序的数据传输功能,同时又能和UDP一样面对消息的方式来进行操作,保护消息边界
- 多宿主
- 多流
- 初始化保护
- 消息分帧
- 可配置的无序发送
- 平滑关闭
SCTP传输问题-多宿主
我们都知道TCP是以字节为单位来传输数据的,但SCTP是 以数据块为单位来传输数据的,这种数据块(DATA CHUNK)通常携带应用的一个数据包,或者是应用要发送的一个消息
SCTP是将应用程序的每次调用sendmsg()发送的数据当做一个整体,放到一个称为DATA CHUNK的数据块里面,接收端也是以数据块为单位来接收,并重新组包,通知应用程序接收,通常应用程序通过recvmesg()都会受到一条完整的消息.
SCTP多路径传输
TCP的两端都只能用一个IP来建立TCP连接,连接之后就能用这一对IP来相互收发消息,如果这一对IP之间的路径出现了问题,那么这条TCP连接就不可用了
SCTP,两端都可以绑定在多个IP上,只要其中一对IP能通,这条SCTP连接就还可以用
SCTP传输问题-多流&无序发送
一条SCTP连接里面,可以区分多条不同的流(stream),不同的流之间的数据传输互不干扰,如果某一条流由于丢包阻塞,其他的流通常也会丢包,被阻塞,最后导致所有的流都被阻塞,SCTP连接中断。
在同一条stream里面,SCTP支持有序/无序两种传输方式,应用程序在调用sendmsg()的时候,需要指定用哪一条stream传输,以及指定这条要发送的消息是需要有序传输还是无序传输的。如果在传输过程中丢包,则有序传递模式可能会在接收端被阻塞,而无序传输模式不会在接收端被阻塞。
SCTP四次握手-初始化保护
TCP中的三次握手机制会被利用来进行DoS攻击,通过发送大量的SYN报文最终耗尽服务器的资源
SCTP通过引入4次握手机制来避免这种场景:
- 服务器的INIT-ACK中会包含cookie(标识这个连接的唯一上下文);
- 客户端使用这个cookie来进行响应。服务器收到这个响应后,才为这个连接分配资源;
- 为了解决4次握手机制带来的时延,SCTP协议还允许在COOKIE-ECHO和COOKIE-ACK报文中传输数据包
SCTP采用UDP方法-消息分帧
UDP使用的是消息分帧,发端多大的数据包,收端收到的数据包也是这么大,SCTP也提供了这种分帧的机制
SCTP的三次断开-平滑关闭
- TCP和SCTP都是基于连接的协议,完成传输后都需要有一个拆除连接的过程。
- TCP中连接的删除是半关闭的,服务的某一端可以关闭自己这端的socket,但是可以继续接受数据。
SCTP协议设计的时候考虑这种半关闭的状态实际上很少使用,所以简化了关闭的过程,一旦某一端发起了连接拆除,对等的两端都关闭。
SCTP协议总结参考链接:
SCTP协议详解 https://blog.csdn.net/wuxing26jiayou/article/details/79743683
SCTP通信协议简介 https://www.jianshu.com/p/08cba3d3eb9f