TCP协议

758 阅读6分钟

OSI七层网络模型

协议层 功能 TCP/IP协议簇
应用层 文件传输,电子邮件,文件服务,虚拟终端 TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet
表示层 数据格式化,代码转换,数据加密 没有协议
会话层 解除或建立与别的节点的联系 没有协议
传输层 提供端对端的接口 TCP,UDP(RTP或一些自定义的协议)
网络层 为数据包选择路由 IP,ICMP,RIP,OSPF,BGP,IGMP
数据链路层 传输有地址的帧以及错误检测功能 SLIP,CSLIP,PPP,ARP,RARP,MTU
物理层 以二进制数据形式在物理媒体上传输数据 ISO2110,IEEE802等

Transfer Control Protocol(传输控制协议,tcp)是面向连接的。它的工作主要是建立连接,然后从应用层程序中接收数据并进行传输。TCP采用虚电路连接方式进行工作,在发送数据前它需要在发送方和接收方建立一个连接,数据在发送出去后,发送方会等待接收方给出一个确认性的应答,否则发送方将认为此数据丢失,并重新发送此数据。


TCP协议结构

TCP header最小为20个字节,结构如下

TCP头结构
定义是:

typedef struct _TCP_HEADER 
{
 short m_sSourPort;                // 源端口号16bit
 short m_sDestPort;                // 目的端口号16bit
 unsigned int m_uiSequNum;         // 序列号32bit
 unsigned int m_uiAcknowledgeNum;  // 确认号32bit
 short m_sHeaderLenAndFlag;        // 前4位:TCP头长度;中6位:保留;后6位:标志位
 short m_sWindowSize;              // 窗口大小16bit
 short m_sCheckSum;                // 检验和16bit
 short m_surgentPointer;        // 紧急数据偏移量16bit
}__attribute__((packed))TCP_HEADER, *PTCP_HEADER;

/*TCP头中的选项定义
kind(8bit)+Length(8bit,整个选项的长度,包含前两部分)+内容(如果有的话).
KIND = 1表示无操作NOP,无后面的部分.
     = 2表示maximum segment, 后面的LENGTH就是maximum segment选项的长度(以byte为单位,1+1+内容部分长度)
     = 3表示windows scale, 后面的LENGTH就是 windows scale选项的长度(以byte为单位,1+1+内容部分长度)
     = 4表示SACK permitted, LENGTH为2,没有内容部分
     = 5表示这是一个SACK包, LENGTH为2,没有内容部分
     = 8表示时间戳,LENGTH为10,含8个字节的时间戳
*/

typedef struct _TCP_OPTIONS
{
 char m_ckind;
 char m_cLength;
 char m_cContext[32];
}__attribute__((packed))TCP_OPTIONS, *PTCP_OPTIONS;

  • 源、目标端口号字段:各16bit。端口号0-65535。在收到服务请求时,操作系统动态地为客户端的应用程序分配端口号。在服务器端,每种服务在"众所周知的端口"(Well-Know Port)为用户提供服务。
  • 序号:占32比特。用来标识从TCP源端向TCP目标端发送的数据字节流,它表示在这个报文段中的第一个数据字节。
  • 确认序号:占32比特。只有ACK标志为1时,确认号字段才有效。它包含目标端所期望收到源端的下一个数据字节。
  • 头部长度字段:占4比特。给出头部占32比特的数目。没有任何选项字段的TCP头部长度为20字节;最多可以有60字节的TCP头部。
  • 标志位:6bit。各bit为1表明该字段。URG(紧急指针有效)、ACK(确认序号有效)、PSH(接收方应尽快将这个报文交给应用层)、RST(重建连接)、SYN(发起连接)、FIN(释放连接)。
  • 窗口大小字段:占16比特。此字段用来进行流量控制。单位为字节数,这个值是本机期望一次接收的字节数。
  • TCP校验和字段:占16比特。对整个TCP报文段,即TCP头部和TCP数据进行校验和计算,并由目标端进行验证。
  • 紧急指针字段:占16比特。它是一个偏移量,和序号字段中的值相加表示紧急数据最后一个字节的序号。
  • 选项字段:占32比特。可能包括"窗口扩大因子"、"时间戳"等选项。

TCP的一些应用

  • 最常见的网络请求http,https就是基于tcp的。常用端口是80
  • FTP(File Transfer Protocol文件传输协议)传输大规模数据,是基于tcp的,常用端口是20/21
  • TELNET远程登录和管理web服务器,常用端口23
  • SMTP(Simple Mail Transfer Protocol)传送邮件,常用端口25.
  • DNS协议,解析域名服务,53端口(但是也有基于UDP的)

TCP建立连接过程

  1. 源主机发送一个同步标志位(SYN)置1的TCP数据段。此段中同时标明初始序号(Initial Sequence Number,ISN)。ISN是一个随时间变化的随机值。
  2. 目标主机发回确认数据段,此段中的同步标志位(SYN)同样被置1,且确认标志位(ACK)也置1,同时在确认序号字段表明目标主机期待收到源主机下一个数据段的序号(即表明前一个数据段已收到并且没有错误)。此外,此段中还包含目标主机的段初始序号。
  3. 源主机再回送一个数据段,同样带有递增的发送序号和确认序号。

TCP三次握手连接

TCP的三次握手保证传输双端的可靠认证,但连接时间过长,业界有提出TCP Fast Open(TFO)的扩展机制,两次握手之后就可以发送正常业务数据了。

TFO扩展机制实现两次握手
扩展阅读可参考:TFO introduction


TCP四次挥手释放连接

由于TCP是全双工协议,传输两端必须都停止数据传输,才能拆除虚链路。

  1. 源主机(可以是客户端,也可以是服务器端),设置Sequence Number和Acknowledgment Number,向目标主机发送一个FIN报文段;此时,源主机进入FIN_WAIT_1状态;这表示源主机没有数据要发送给目标主机了;
  2. 目标主机收到了源主机发送的FIN报文段,向源主机回一个ACK报文段,Acknowledgment Number为Sequence Number加1;源主机进入FIN_WAIT_2状态;目标主机告诉源主机,我“同意”你的关闭请求;
  3. 目标主机向源主机发送FIN报文段,请求关闭连接,同时目标主机进入LAST_ACK状态;
  4. 源主机收到目标主机发送的FIN报文段,向目标主机发送ACK报文段,然后源主机进入TIME_WAIT状态;目标主机收到源主机的ACK报文段以后,就关闭连接;此时,源主机等待2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,源主机也可以关闭连接了。

TCP挥手


TCP慢启动

1)刚开始的时候将发送端拥塞窗口设置得很小,也就是一个MSS值(TCP发送端满足发送打包的最大报文长度,这个MSS值是为了防止数据内容太少,报头内容太多而设定) 2)逐步试探,指数增长拥塞窗口,直到到达ssthresh(慢开始门限,表示此时窗口增长速度变慢) 3)此时改用拥塞避免算法,递加增长拥塞窗口。

慢启动和拥塞避免,盗图


线头阻塞

是指由于TCP协议的可靠性传输特征,发送端的发送序列是一个FIFO的队列。如果在前面已发送的数据,发现有丢包的情况。那么这时候需要等到丢掉的数据包重传并收到ACK以后,发送队列里的数据才能继续传输。 这样就相当于前面的header,造成了后面数据的阻塞。因此成为Header of line(HOL)


some articles

TCP难点 TCP流量控制和拥塞控制