标签:set 推荐阅读 序列 检查 off ati str 链接 https
TCP是TCP/IP协议栈的核心组成之一,对开发者来说,学习、掌握TCP非常重要。
本文主要内容包括:什么是TCP,为什么要学习TCP,TCP协议格式,通过实例讲解TCP的生命周期(建立连接、传输数据、断开连接)
传输层控制协议(Transport Control Protocol),TCP/IP协议栈的核心之一。位于应用层与网络层之间,提供面向连接的、可靠的字节流服务。
记住关键词“面向连接”、“可靠”、“字节流”,这是学习掌握TCP的关键:
TCP花了大量的功夫在确保传输层服务的可靠性上,具体举措包括(但不限于)以下:
TCP传输服务的可靠性对应用层的开发者来说至关重要。作为应用层的开发者(比如HTTP server),除了业务逻辑之外,如果还需要操心数据是否正常送达,接收到的数据是否完整,开发效率会相当低下。
参考自《TCP/IP详解卷一》,推荐阅读
TCP首部格式如下图所示,在不包含可选字段的情况下,大小通常为20个字节。部分字段定义可能并不直观,如果读者觉得某些首部字段不好理解,建议先跳过,结合后文的实例可能更容易理解些。
比如 Sequence Number/Acknowledgment Number/ACK/SYN,结合TCP建立连接的过程来看,会更好理解。
这里留个小问题给读者:怎么知道TCP报文段数据(data)的长度是多少?
Source Port(来源端口):16位
Destination Port(目的端口):16位
Sequence Number(序号):32位
TCP报文段中的数据部分,每一个字节都有它的序号(递增)。根据控制标志(Control Bits)中的SYN是否为1,Sequence Number 表达不同的含义:
Acknowledgment Number(确认序号):32位
当控制标志的ACK为1时,表示发送方希望收到的下一个报文段的序号(Sequence Number)。一旦连接建立成功,ACK值一直为1。
Data Offset(数据偏移量):4位
TCP报文段的首部长度,单位是word(4字节)。字面含义是:TCP报文段的数据的起始处,距离TCP报文段的起始处 的偏移量。4个字节最大能表示的数字是15,所以首部最大60字节。
Reserved(保留字段):6位
预留作为后续用途,必须是0。
Control Bits(控制标志):6位
一共有6个控制标志,其中SYN/ACK、FIN/ACK主要用于连接的建立、断开阶段。
Window Size(窗口大小):16位
允许对方发送的数据量。告诉对方自己缓冲区还能容纳多少字节,用来控制对方发送数据的速度。
比如,服务端发送给客户端的TCP报文段中,确认序号是701,窗口字段(Window Size)是1000,表明服务端能够接受客户端发来的,序号从701开始的1000字节数据。
Checksum(校验和):16位
发送端对TCP首部、数据进行CRC运算得出的结果。接收端收到数据后,对接收到的TCP报文段的首部、数据进行CRC运算,并跟TCP首部中的校验和进行对比,确保数据在传输过程中没有损坏。
计算、校验规则这里先不展开。
Urgent Pointer(紧急指针):16位
仅在URG=1时才生效,它的值是一个偏移量,和序号字段中的值相加得到紧急数据最后一个字节的序号。
options(可选字段):大小不固定
最常见的可选字段是MSS(Maximum Segment Size),表示最长报文大小,通信双方通常在连接的第一个报文段中指明这个选项。(只能出现在SYN报文中)
TCP的两段正式开始传输数据前,需要先建立连接。一旦数据传输完成,则需要断开连接。
后面章节中,会通过实际例子说明TCP数据传输的完整生命流程。在这之前,先简单介绍下TCP是如何建立连接以及断开连接的,也就是我们所熟悉的3次握手以及4次挥手。
这里留几个问题给读者朋友:
Seq => Sequence Number,Ack => Acknowledgment Number,[SYN] => 控制标志SYN,[ACK] => 控制标志ACK
一般情况下,握手流程如 下图 所示,主要做了两件事情:
一般情况下,TCP断开连接需要4次挥手。假设 TCP A 主动断开连接,流程如下。主要就是告知对方,自己准备断开连接了,并且等待对方的确认。
在这一小节,会通过例子,阐述TCP从建立连接,到数据传输,到最后断开连接的整个过程,并通过wireshark抓包探究一些通信的细节。
首先,打开wireshark监听网络请求。然后,在终端输入如下命令发送HTTP请求。
curl http://id.qq.com/index.html
下面为wireshark抓包截图,分为3个部分,分别为 (1)建立连接,(2)数据传输,(3)断开连接。
1、本地 -> 服务端:[SYN] Seq=0;
备注:本例子中中,客户端、服务端的初始Seq值其实不是0,截图中展示的0是个相对值,是wireshark为了方便开发者进行抓包分析转化过来的。
2、服务端 -> 本地:[SYN, ACK] Seq=0, Ack=1;
3、本地 -> 服务端:[ACK] Seq=1, Ack=1
到这里,双方连接建立,开始交换数据
数据交换是双向的,这里以服务端的HTTP响应为例子。响应内容较大,被拆成了多个TCP包。整个数据发送的过程,就是服务端向客户端发送数据,客户端向服务端发送确认的过程。
1.1、服务端->客户端:Seq=1,TCP数据长度273。也就是说,服务端发送的报文段中,第一个数据字节的序号是1;下一个TCP报文段,第一个数据字节的序号应该是274。
1.2、客户端->服务端:Ack=274。表示客户端已经收到序号274之前的所有字节;也就是说,服务端如果继续给客户端发送TCP报文,应该发送序号274及以后的数据。
2.1、服务端->客户端:Seq=274,TCP数据长度1400。也就是说,服务端发送的报文段中,第一个数据字节的序号是274;下一个TCP报文段,第一个数据字节的序号应该是1674(274 + 1400)。
2.2、。。。
后面的分析过程同上。
从抓包中看到比较有意思的点。当服务端收到客户端的断开请求时(FIN=1),服务端在同一个响应包里发送了FIN、ACK,达到了减少一个数据包的效果。
笔者在前端招聘的面试中,经常会问一些网络基础方面的问题,经常会有面试者感到困惑:为什么要问这些问题?这些知识是他们需要掌握的吗?好像跟工作关联不大?
这可能是普遍的误区。
掌握HTTP协议的重要性不用强调,WEB开发者的基础要求之一。但是,有必要学习TCP吗?这个问题倒是值得思考一下。
答案是:很有必要。
举个例子:
WebSocket是基于TCP的,并复用了HTTP的握手通道。如果开发者对HTTP、TCP没有一定的了解,那么在使用WebSocket的时候,WebSocket对他来说就像一个黑盒,充满了各种黑科技。WebSocket、HTTP两者有什么关联?WebSocket跟Socket.io有什么关联?为什么服务端开启多个Socket.io实例,并通过反向代理进行转发后,连接握手就会失败?
如果开发者对HTTP、TCP足够了解,在遇到上面的问题时,就不至于毫无头绪。
再举个例子:
在探究性能优化时,经常会提到HTTP/2。什么是HTTP/2,为什么说HTTP/2的性能比HTTP 1.1好?什么是HTTP/2的多路复用?是怎么实现的?有什么好处?
同样的,如果对HTTP、TCP足够了解,上面的问题并不难回答,翻翻书或协议,至少能够回答个大概。
TCP/IP由复杂的协议栈组成,而TCP是协议栈中的核心部分。TCP协议本身非常复杂,本文只是对基础部分进行了讲解,还有许多内容尚未覆盖到,比如TCP的超时重传机制、拥塞控制机制等,后面有时间再继续展开。
如有错漏,敬请指出。
《TCP/IP详解卷一》
Difference between push and urgent flags in TCP
Calculate size and start of TCP packet data (excluding header)
Why do we need a 3-way handshake? Why not just 2-way?
原文地址:https://www.chyingp.com/posts/understanding-tcp/
标签:set 推荐阅读 序列 检查 off ati str 链接 https
原文地址:https://www.cnblogs.com/chyingp/p/understanding-tcp.html