<commit_before><commit_msg>block data over tcp<commit_after>---
title: TCP/IP协议之TCP的成块数据流  
categories: network  
tag:    
- tcp/ip  

---
  

TCP使用滑动窗口协议的另一种方式来实现流量控制。该协议允许发送方在停止并等待确认之前可以连续发送**多个分组**。由于发送方不必每发送一个分组就停下来等确认，因此该协议可以加速数据的传输。  
## 一、滑动窗口  
![-w500](http://oda58fqub.bkt.clouddn.com/14899121797587.jpg)    

接收方通告的窗口称之为提供的窗口 (offered window) 。  
当接收方确认数据以后，这个滑动窗口不时向右移动。  

1. 称窗口左边沿向右边沿靠近为窗口合拢 (close)。发生在发送的数据被确认 (data is sent and acknowedged)。  
2. 窗口右边沿向右移动时，允许发送更多的数据，称之为窗口张开 (open)。发生在另一端的接收进程读取已经确认的数据并释放了TCP的接收缓存。  
3. 右边沿向左移动时，称之为窗口收缩 (shrink)。RFC强烈建议不要使用这种方式，但TCP必须能够在某一段产生这种情况时进行处理。  
 
![-w500](http://oda58fqub.bkt.clouddn.com/14899127629704.jpg)  


1. 发送方不必发送一个全窗口大小的数据  
2. 来自接收方的一个报文段确认数据将窗口向右滑动  
3. **窗口的大小可以减小，但是窗口的右边沿不能向左移动**  
4. 接收方在发送一个ACK之前不必等待窗口被填满   

### 窗口大小    
由接收方提供的窗口的大小通常可以由接收进程控制，窗口大小将影响TCP的性能。  

## 二、PUSH标志  
发送方使用该标志通知接收方将所收到的数据全部交给接收进程。这里的数据包括**与PUSH一起传送的数据以及接收方TCP已经为接收进程收到的其他数据**。  
由于源于伯克利的实现一般从不将接收到的数据推迟交付给应用程序，因此他们忽略所接收的PUSH标志。  

## 三、慢启动 (slow start)  
如果发送方一开始就向网络发送多个报文段，直至达到接收方通告的窗口大小为止，并且在发送方和接收方之间存在多个路由器和速率较慢的链路时，会出现一些问题。一些中间的路由器必须缓存分组，并有可能耗尽存储器的空间。  
慢启动通过观察到新分组进入网络的速率应该与另一端返回确认的速率相同而进行工作。  
慢启动为发送方的TCP增加了另一个窗口：拥塞窗口 (congestion window)，记为cwnd。当与另一个网络的主机建立TCP连接时，拥塞窗口被初始化为1个报文段。每收到一个ACK，拥塞窗口就增加一个报文段。发送方取拥塞窗口与通告窗口中的最小值作为发送上限。  
**拥塞窗口是发送方使用的流量控制，而通告窗口则是接收方使用的流量控制。**  
慢启动中拥塞窗口的增长是指数关系 (1->2->4...)。    
当达到互联网容量时，中间路由器会丢弃分组，通知发送方它的拥塞窗口开的太大。发送方会调整拥塞窗口。  

## 四、窗口大小的选择    
### 带宽时延积  
发送端和接收端之间通道的容量是：  
$$capacity(bit) = bandwidth(b/s) \times roundtrip\ time(s)$$  
一般称之为带宽时延积。这个值依赖于网络速度和两端的RTT。无论是带宽还是时延，都会影响发送方和接收方之间通路的容量。    
一般窗口的大小不应大于带宽时延积，否则会引起拥塞。  
### 拥塞  
当一个大的管道并向一个较小的管道发送时便会发生拥塞。  
当多个输入流导到一个路由器，而路由器的输出流小于这些输入流的总和时，也会发生拥塞。  
![-w500](http://oda58fqub.bkt.clouddn.com/14899160068525.jpg)  

## 五、紧急方式  
TCP提供了“紧急方式 (urgent mode)”，它使一端可以告诉另一端有些具有某种方式的“紧急数据”已经放置在普通的数据流中。另一端被通知这个紧急数据已被放置在普通普通数据流中，由接收方决定如何处理。  
![-w500](http://oda58fqub.bkt.clouddn.com/14899162773964.jpg)  

首部中的两个字段被用来通知紧急数据已经被放置在数据流中。

1. URG比特被置为1  
2. 一个16bit的紧急指针被置为一个正的偏移量。该偏移量和TCP首部中的序号字段相加，得出紧急数据的最后一个字节序号。  
{'fraction_non_alphanumeric': 0.11186440677966102, 'fraction_numerical': 0.04455205811138015, 'mean_word_length': 6.651851851851852, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6034083', 'n_tokens_mistral': 1681, 'n_tokens_neox': 2013, 'n_words': 82}