小白笔记
本节学习面向连接的传输:TCP
这种TCP“连接”不是一条像在电路交换中的端到端TDM或FDM电路。相反,该“连接”是一条逻辑连接,其共同状态仅保留在两个通信系统的TCP程序中。前面讲过,由于TCP协议只是在端系统中运行,而不在中间的网络元素(路由器和链路层交换机)中运行,使用之间的网络元素不会维持TCP连接状态。事实上,中间路由器对TCP连接完全视而不见,他们看到的是数据报,而不是连接。
1.段结构:
TCP:概述 RFCs:793,1122,1323,2018,2581
·点对点: ·一个发送方 ·一个接收方
·可靠的、按顺序的字节流: ·没有报文边界
·管道化(流水线): ·TCP拥塞控制和流量控制窗口大小
·发送和接收缓存
·全双工数据: ·在同一连接中数据流双向流动(就比如上层往下层交东西的时候,下层也可以往上层交东西) ·MSS:最大报文段大小(报文如果非常长就必须要分成一个个的MSS的大小,之后运输层每个MSS的大小加上一个TCP的头部形成TCP段,到了网络层再加上RP头部,然后正好能够被封装在以太网帧或者其他网络的MTU的载荷部分中,那么就不存在分片这样的一个问题,MTU:最大传送单元,意思是IP数据报的最大长度不包括帧头帧尾)
·面向连接: ·在数据交换之前,通过握手(交换控制报文)初始化发送方、接收方的状态变量
·有流量控制:·发送方不会淹没接收方
我们考虑一下从客户进程向服务器进程发送数据的情况。
如图所示,客户进程通过套接字传输数据流,数据一旦通过该门,它就由客户中运行的TCP控制了。TCP将这些数据引导到该连接的发送缓存里,发送缓存是发起三次握手期间设置的缓存之一。接下来TCP就会不时从发送缓存里取出一块数据,并将数据传递到网络层。TCP可从缓存中取出并放入报文段中的数据数量受限于最大报文段长度(MSS)MSS通常根据最初确定的由本地发送主机发送的最大链路层帧长度(即所谓的最大传输单元(MTU))来设置,设置该MSS要保证一个TCP报文段(当封装在一个IP数据报中)加上TCP/IP首部长度将适合单个链路层帧。注意MSS是指在报文段里应用层数据的最大长度,而不是包括首部的TCP报文段的最大长度(该术语容易混淆)。
TCP报文段结构
序号:是以字节为单位的序号而不是前面例子讲到分组的序号,这里序号指的是上面发下来的报文字节流,是按照MSS为单位切成一块一块的报文段(被切成一块块的MSS还是连在一起的),那么每个TCP有头部有body部分,body部分就是它的载荷部分,每个被切成一块块的报文段的载荷的第一个字节表示的即是在报文中的偏移量(偏移量即对应的字节流中某个MSS开头到整个字节流开头的距离),所以序号不一定是连续加1的可能加若干。序号,即报文段首字节的在字节流的编号。
确认号:·期望从另一方收到的下一个字节的序号 ·累积确认(确认n-1及以前字节)
TCP往返延时(RTT)和超时
1)怎样设置TCP超时?
·比RTT要长,但RTT是变化的
·太短:太早超时,不必要的重传
·太长:对报文段丢失反应太慢,消极
2)怎样评估RTT?
·SampleRTT:测量从报文段发出到收到确认的时间,若干有重传,忽略此次测量
·SampleRTT会变化,因此估计的RTT应该比较平滑
·对几个最近的测量值求平均,而不是仅仅用当前的SampleRTT
2.TCP:可靠数据传输
·TCP在IP不可靠服务的基础上建立了rdt
·管道化的报文段(GBN orSR) (在未经确认的情况下可以一次发送很多段)
·累积确认(像GBN)
(跟GBN有点一样,确认发的是顺序接收到的最后一个TCP段加1,比如接收到了1-54,则返回55,而不是返回ACK1->ACK54,也不是返回ACK54,而是返回ACK55,如果收到ACK=55,则说明接收方已经收到54以及之前的所有分组,并且希望发送方从55开始传输)
·单个重传定时器(像GBN)(但是注意哦,超时后它不是全部重传,而是只传最早未确认的那个段,这里就又像SR了)
·是否可以接受乱序的,可以接收也可以丢掉是没有规范的
·通过以下事件触发重传
·超时(只重发那个最早的未确认段:SR)
·重复的确认(例子:收到了ACK50之后又收到3个ACK50)
·首先考虑简化的TCP发送方:
·忽略重复的确认
·忽略流量控制和拥塞控制
TCP发送方事件:
从应用层接收数据:
·用nextseq创建报文段
·序号nextseq为报文段首字节是字节流编号
·如果还没有运行,启动定时器
·定时器与最早未确认的报文段相关联
·过期间隔:TimeOutInterval
超时:
·重传后沿着最老的报文段
·重新启动定时器
收到确认:
·如果是对尚未确认的报文段确认
·更新已被确认的报文序号
·如果当前还有未被确认的报文段,重新启动定时器
如图,例子1:发送方发送92,8字节数据即发送92-99,接收方接收到了92-99 ,注意这时候接收方发的是ACK100而不是ACK99哈,可是过程中丢失了,导致超时重传,所以接收方会重发这个段92-99,注意哈,重传的是一个段,这个段里有92-99 ,注意并不是只传99,重传的是最后未确认的段是段。
如图,例子2:发送方发送92-99,然后不一会儿又发100-119,92-99回来的ACK超时了,这时候会重新启动超时定时器,重新发送最老的段即92-99这个段的时候发送方接收到了ACK120,这时候发送方就知道接收方已经接收到119及119之前的数据了,所以发送方发送完92-99后得到的确认是ACK120,而不是ACK100,注意哟。
产生TCP ACK的建议 [RFC 1122,RFC 2581]
接收方的事件 | TCP接收方动作 |
所期望序号的报文段按序到达。 所有在期望序号之前的数据都已经被确认 | 延迟的ACK。对另一个按序报文段的到达最多等待500ms。如果下一个报文段在这个时间间隔内没有到达,则发送一个ACK。 比如y1之前的全部按序接收到了,接下来要发ACKy1吗,不,先等500ms,如果这500ms内y1的下一个即y2到了就发ACKy2(节省发y1了嘛,这就是下面的发送单个累计ACK),如果这500ms y2没来则发送ACKy1催y1来。 |
有期望序号的报文段到达。另一个按序报文段等待发送ACK。 | 立即发送单个累积ACK,以确认两个按序报文段。 |
比期望序号大的报文段乱序到达。检测处数据流中的间隔 | 立即发送重复的ACK,指明下一个期待字节的序号。 比如y1到了,而y1前面的y0还没到则赶紧发送ACKy1,催它快点补发y1过来 |
能部分或完全填充接收数据间隔的报文段到达 | 若该报文段起始于间隔(gap)的低端,则立即发送ACK。 比如如果y0、y1还没到y2就到了,然后如果y1,y2补上了,则发送y2的后一个ACKy3,如果只补上了y0,则立即发送ACKy1 |
快速重传
·超时周期往往太长:在重传丢失报文段之前的延时太长
·通过重复的ACK来检测报文段丢失
·发送方通常连续发送大量报文段
·如果报文段丢失,通常会引起多个重复的ACK
·如果发送方收到同一数据的3个冗余ACK,重传最小序号的段
·快速重传:在定时器过时之前重发报文段
·它假设跟在被确认的数据后面的数据丢失了
·第一个ACK是正常的
·收到第二个该段的ACK,表示接收方收到一个该段后的乱序段
·收到第3,4个该段的ack,表示接收方收到该段之后的2个,3个乱序段,可能性非常大段丢失了
比如假设有5个段,第1段到了,这时候就传回ACK2,第2段还没到,第3段到了,这时候又传回ACK2,然后第4段又到了又返回了ACK2而第2段还是没到也还没超时,然后第5段又到了又返回了ACK2,还是没超时,所以还是不能因为超时而重传,但是已经传回3个冗余的ACK2了,所以即使没有超时也重传第2段了,就是快速重传。
3.TCP:流量控制
流量控制:接收方控制发送方,不让发送方发送的太多,太快以至于让接收方的缓冲区溢出。
·接收方在其向发送方的TCP段头部的rwnd字段“通告”其空闲buffer大小
·RcvBuffer大小通过socket选项设置
·很多操作系统自动调整RcvBuffer
·发送方限制未确认(“in-flight”)字节的个数<=接收方发送过来的rwnd值
·保证接收方不会被淹没
很多人容易把流量控制和拥塞控制混淆。
TCP通过让发送方维护一个称为接收窗口的变量来提供流量控制,通俗点说,接收窗口用于给发送方一个指示--该接收方还有多少可用的缓存空间。
4.连接管理(我们主要讲连接建立和连接拆除)
在正式交换数据之前,发送方和接收方握手建立通信关系:
·同意建立连接(每一方都知道对方愿意建立连接)
·同意连接参数
连接是两个应用基础建立起TCP的连接,连接的本质是什么,第一个要素是,双方知道要和对方通信,第二个要素,是为这次通信要准备好一些缓冲区,作为发送方接收方都要准备好一些缓冲区,第三个要素,控制变量要做一些置位,连接建立的时候双方初始序号和revbuffer的大小要互相告诉对方并且互相确认。所以TCP的建立本质上是三次握手,不是嗨过来嗨过去就完啦。
同意连接
在网络中,2次握手建立连接总是可行的吗?
·变化的延迟(请求连接的段没有丢,但可能超时)
·由于丢失造成的重传(e.g.req_com(x))
·报文乱序
·互相看不到对方
两次握手不行,解决方案是三次握手
三次握手:
3次握手可以避免2次连接所带来的问题,避免第一个问题维持了虚假的连接,第二个问题服务器把旧数据当新数据接收了这样的一个问题。为什么要三次连接?本质上是我把我的选择初始序号给你并且给我确认,你把你的选择初始序号给我并且我给你确认,例如,发送方给接收方x,接收方回复ACK=x+1和y,然后发送方给接收方ACK=y+1,这样发送方就知道接收器以后要从x+1及以后开始传,接收器知道发送方以后要从y+1及以后开始传,因为双方都需要告诉对方自己的初始序号并且得到确认,最少需要三次交互才能完成。
3次握手解决:半连接和接收老数据问题
TCP:关闭连接
客户端,服务器任何一侧都能关闭连接。客户端,服务器分别关闭它自己这一侧的连接。
·发送FIN bit=1的TCP段
·一旦接收到FIN,用ACK回应
·接到FIN段,ACK可以和它自己发出的FIN段一起发送
·可以处理同时的FIN交换
例如,假设某客户打算关闭连接,如图,客户应用进程发出一个关闭连接命令。这会引起客户TCP向服务器进程发送一个特殊的TCP报文段。这个特殊的报文段让其首部中的一个标志位即FIN比特被设置为1。当服务器接受到该报文段后,就发回一个确认报文段。然后,服务器发送它自己的终止报文段,其FIN比特被置为1。最后,该客户对这个服务器的终止报文段进行确认。此时,在两台主机上用于该连接的所有资源都被释放了。