Getting started with TCP Sequence and Acknowledgement Numbers
开始了解 TCP 序列号和确认号
TCP (Transmission Control Protocol) is a connection oriented and highly reliable protocol. Before data exchange between two parties, it requires to establish a connection, using TCP 3-way handshaking. The connection remains active until it gets terminated. During 3-way handshaking both sides synchronize (SYN) and acknowledge (ACK) each other. In another saying, they inform each other about what kind of settings they would like to use during the connection establishment. The settings include Sequence Number, Maximum Segment Size, if SACK is permitted or not, Window Scale, Window Size etc. See below for a SYN packet which contains an initiator (a client) settings.
TCP(传输控制协议)是一种面向连接且高度可靠的协议。在两方进行数据交换之前,需要通过 TCP 三次握手建立连接。连接一直保持活动状态,直到被终止。在三次握手中,双方会进行同步(SYN)和确认(ACK)。换句话说,它们会告知对方在建立连接时希望使用的设置类型。这些设置包括序列号、最大报文段长度、是否允许 SACK、窗口缩放、窗口大小等。下面是一个包含发起方(客户端)设置的 SYN 数据包。
In this article, we will closely examine Sequence Number and Acknowledgement Number with Wireshark. For better understanding, we will capture a TCP flow and analyse it. I will visit the first web page published on the internet, which is pretty simple. If you wonder to see what它 is like, link is here: The World Wide Web project
Stop capturing, now we should have the packets. See my captures below.
停止捕获,现在我们应该有了数据包。看看我的捕获结果。
Go to Statistics → Flow Graph to see more details.
前往 统计 → 流图 以查看更多详细信息。
The figure above explains everything about the flow. First 3 packets --SYN, SYN/ACK and ACK-- are used to establish a connection before any data is exchanged. This step is called TCP 3-way handshaking. Next, the client sends a http GET request on the top of TCP and the server responds it back with a http 200 OK, which indicates that the request has succeeded. The last 4 packets are exchanged to tear down the connection.
上图解释了关于流的所有内容。前三个数据包------SYN、SYN/ACK 和 ACK------用于在任何数据交换之前建立连接。这一步称为 TCP 三次握手。接下来,客户端在 TCP 上发送一个 http GET 请求,服务器以 http 200 OK 响应,表示请求成功。最后四个数据包用于拆除连接。
Breaking down to Packet by Packet Analysis
逐包分析
Packet Number 1
第 1 个数据包
We will analyse the flow packet by packet, starting from the first packet. For visualization, see screen shot below.
我们将逐包分析流量,从第一个数据包开始。为了可视化,请参阅下面的屏幕截图。
This is the first packet (it is also called SYN packet) from the client to the server with source and destination port of 62834, 80 respectively.
这是客户端到服务器的第一个数据包(也称为 SYN 数据包),源端口和目的端口分别为 62834 和 80。
All data in a TCP connection are numbered, starting at a randomly chosen ISN (Initial Sequence Number). Although the first packet (SYN) does not contain any data, it consumes one sequence number and as a result the actual data begins at ISN+1. For easy understanding, Wireshark starts ISN from zero which is called "relative sequence number " while in the screen shot above, we can clearly see the client has set its real sequence number to 332215980. Relative sequence number is just for easy analyzing. Since this is the first packet in the flow, acknowledgement number is set to zero. With these settings, the client informs the server that it will use some options and asks the server to send its options as well in the next packet (SYN/ACK).
The second packet (it is also called SYN/ACK packet) from the server to the client is pretty similar to the first packet, except ACK flag being set to 1 this time. Even though, this packet is not carrying any data but connection settings, the acknowledgement number is increased by 1 which tells the client it has received the SYN packet while it sets its sequence number to zero.
从服务器到客户端的第二个数据包(也称为 SYN/ACK 数据包)与第一个数据包非常相似,只是这次 ACK 标志被设置为 1。尽管这个数据包没有携带任何数据,只有连接设置,但确认号增加了 1,这告诉客户端它已经收到了 SYN 数据包,同时将其序列号设置为零。
Packet Number 3
第 3 个数据包
This is the last packet (it is also called ACK packet) for TCP 3-way handshaking. The client increases its sequence and acknowledgement number by 1, letting the server know it has received its SYN/ACK packet. From this point, the sequence and the ack numbers will increase only after one end has sent or received some data.
This is the first packet that contains some actual data (373 bytes of HTTP Get request), which is also called TCP payload. The sequence numbers are accumulated during the conversation. In another saying, the client let the server know how much data it has sent in total by sequence number. it also specifies amount of data in total it has received from the server by acknowledgement number. Since, it has not sent or received any data before, the sequence and the acknowledgement numbers remain 1.
这是第一个包含实际数据(373 字节的 HTTP GET 请求)的数据包,也称为 TCP 负载。序列号在对话过程中不断累积。换句话说,客户端通过序列号让服务器知道它总共发送了多少数据,同时也通过确认号指定了它从服务器总共接收了多少数据。由于它之前没有发送或接收过任何数据,因此序列号和确认号保持为 1。
Packet Number 5
第 5 个数据包
This packet does not carry any data as you see from len: 0 . Once the server receives 373 bytes of data, it needs to let the client know that it has received the data with ACK flag set. Since the server has not sent any data before, it sets its sequence number to 1 while the acknowledgement number increases by 373 to 374. In short, the server tells the client it got 373 bytes of data and it expects new data starting from number of 374.
After receiving the http GET request, the server creates a http response and breaks it into 2 pieces, since total response size exceeds TCP maximum segment size (1452 bytes, it is present in the second packet) which both side agreed on during TCP 3-way handshaking. The length of the data is 1452 bytes. The server sends the packet with the same sequence and acknowledgement number.
This is the second piece of the http response from the server with size of 998 bytes. you can see the sequence number has increased by 1452, because it sent that amount of data to the client in the previous packet while the acknowledgement number still remains the same.
The server has no data to send and it wants to acknowledge the client that it would like to terminate the TCP connection with the fin flag set. The packet carries no data. The sequence number increases by 998 to 2451, which indicate that it has sent 2450 bytes until now. Since there has not been any change in amount of data receiving from the client, the acknowledgement number remains the same.
服务器没有数据要发送,它希望通过设置 FIN 标志来告知客户端它希望终止 TCP 连接。该数据包不携带任何数据。序列号增加了 998,达到 2451,这表明它到目前为止已经发送了 2450 字节。由于从客户端接收的数据量没有变化,确认号保持不变。
Packet Number 9
第 9 个数据包
The client acknowledges the server that it has received its data by setting the acknowledgment number to 2452, which indicates that the server should send the data starting from 2452 next time (if it has any).
With this packet, the client informs the server that it also would like to terminate the connection with the fin flag set.
通过这个数据包,客户端告知服务器它也希望通过设置 FIN 标志来终止连接。
获取 TCP 序列和确认编号基础知识的简单示例
TCP Sequence and Acknowledgement Numbers Explained
TCP 序列和确认编号说明
TCP Sequence (seq) and Acknowledgement (ack) numbers help enable ordered reliable data transfer for TCP streams. The seq number is sent by the TCP client, indicating how much data has been sent for the session (also known as the byte-order number). The ack number is sent by the TCP server, indicating that is has received cumulated data and is ready for the next segment.
The TCP seq and ack numbers are coordinated with one another and are key values during the TCP handshake, TCP close, and, of course, while data is transferred between the client and server.
By default, Wireshark converts all sequence and acknowledgement numbers into [relative numbers](https://wiki.wireshark.org/TCP_Relative_Sequence_Numbers). This means that all SEQ and ACK numbers always start at 0 for the first packet seen in each conversation.
The picture below shows a real example of TCP sequence and acknowledgment numbers in a TCP flow diagram. The key variable is the TCP segment length for each TCP segment sent in the session.
The client sends the first segment with seq=1 and the length of the segment is 669 bytes. The server responds with an ack=670 which tells the client that the next expected segment will have a sequence number is 670.
The next segment the client sends has seq=670 and the len is now 1460 bytes. In turn, the server responds with ack=2130 (670 + 1460). This cycle continues until the end of the TCP session.
Again, note that the length value is from the TCP segment length, not the Layer 2 frame length nor the IP packet length.
同样,请注意,length 值来自 TCP 分段长度,而不是第 2 层帧长度或 IP 数据包长度。
Seq and Ack in Wireshark
Wireshark 中的 Seq 和 Ack
Client sends seq=1 and tcp segment length=669
客户端发送 seq=1 且 tcp 段长度 = 669
Server responds with ack=670
服务器响应 ack=670
Client sends segment with seq=670 and length=1460
客户端发送 seq=670 且 length=1460 的 segment
Server responds with ack=2130
服务器响应 ack=2130
This is just a simple example to get the basics of TCP sequence and acknowledgement numbers.
Understanding TCP Sequence and Acknowledgment Numbers
了解 TCP 序列和确认编号
By stretch | Monday, June 7, 2010 at 2:15 a.m. UTC
If you're reading this, odds are that you're already familiar with TCP's infamous "three-way handshake," or "SYN, SYN/ACK, ACK." Unfortunately, that's where TCP education ends for many networkers. Despite its age, TCP is a relatively complex protocol and well worth knowing intimately. This article aims to help you become more comfortable examining TCP sequence and acknowledgment numbers in the Wireshark packet analyzer.
Before we start, be sure to open the example capture in Wireshark and play along.
在开始之前,请务必在 Wireshark 中打开示例捕获并一起玩。
The example capture contains a single HTTP request to a web server, in which the client web browser requests a single image image file, and the server returns an HTTP/1.1 200 (OK) response which includes the file requested. You can right-click on any of the TCP packets within this capture and select Follow TCP Stream to open the raw contents of the TCP stream in a separate window for inspection. Traffic from the client is shown in red, and traffic from the server in blue.
TCP utilizes a number of flags, or 1-bit boolean fields, in its header to control the state of a connection. The three we're most interested in here are:
TCP 在其标头中使用许多标志或 1 位布尔字段来控制连接的状态。我们在这里最感兴趣的三个是:
SYN - (Synchronize) Initiates a connection
SYN - (同步)启动连接
FIN - (Final) Cleanly terminates a connection
FIN - (最终)完全终止连接
ACK - Acknowledges received data
ACK - 确认接收到的数据
As we'll see, a packet can have multiple flags set.
正如我们将看到的,一个数据包可以设置多个标志。
Select packet #1 in Wireshark and expand the TCP layer analysis in the middle pane, and further expand the "Flags" field within the TCP header. Here we can see all of the TCP flags broken down. Note that the SYN flag is on (set to 1).
Now do the same for packet #2. Notice that it has two flags set: ACK to acknowledge the receipt of the client's SYN packet, and SYN to indicate that the server also wishes to establish a TCP connection.
现在对数据包 #2 执行相同的作。请注意,它设置了两个标志:ACK 确认收到客户端的 SYN 数据包,SYN 表示服务器也希望建立 TCP 连接。
Packet #3, from the client, has only the ACK flag set. These three packets complete the initial TCP three-way handshake.
来自客户端的数据包 #3 仅设置了 ACK 标志。这三个数据包完成初始 TCP 三次握手。
Sequence and Acknowledgment Numbers
序列号和确认编号
The client on either side of a TCP session maintains a 32-bit sequence number it uses to keep track of how much data it has sent. This sequence number is included on each transmitted packet, and acknowledged by the opposite host as an acknowledgment number to inform the sending host that the transmitted data was received successfully.
When a host initiates a TCP session, its initial sequence number is effectively random; it may be any value between 0 and 4,294,967,295, inclusive. However, protocol analyzers like Wireshark will typically display relative sequence and acknowledgment number in place of the field's actual value. These values are relative to the initial sequence number of that stream. This is handy, as it is much easier to keep track of relatively small, predictable numbers rather than the actual numbers sent on the wire.
For example, the initial relative sequence number shown in packet #1 is 0 (naturally), while the ASCII decode in the third pane shows that the actual sequence number is 0xf61c6cbe, or 4129057982 decimal.
The display of relative sequence numbers can optionally be disabled by navigating to Edit > Preferences... and un-checking Relative sequence numbers and window scaling under TCP protocol preferences. However, be aware that the remainder of this article will reference relative sequence and acknowledgment numbers only.
To better understand how sequence and acknowledgment numbers are used throughout the duration of a TCP session, we can utilize Wireshark's built-in flow graphing ability. Navigate to Statistics > Flow Graph... , select TCP flow and click OK . Wireshark automatically builds a graphical summary of the TCP flow.
Each row represents a single TCP packet. The left column indicates the direction of the packet, TCP ports, segment length, and the flag(s) set. The column at right lists the relative sequence and acknowledgment numbers in decimal. Selecting a row in this column also highlights the corresponding packet in the main window.
We can use this flow graph to better understand how sequence and acknowledgment numbers work.
我们可以使用此流程图来更好地了解序列和确认数字的工作原理。
Packet #1
数据包 #1
Each side of a TCP session starts out with a (relative) sequence number of zero. Likewise, the acknowledgment number is also zero, as there is not yet a complementary side of the conversation to acknowledge.
(Note: The version of Wireshark used for this demonstration, 1.2.7, shows the acknowledgment number as an apparently random number. This believed to be a software bug; the initial acknowledgment number of a session should always be zero, as you can see from inspecting the hex dump of the packet.)
The server responds to the client with a sequence number of zero, as this is its first packet in this TCP session, and a relative acknowledgment number of 1. The acknowledgment number is set to 1 to indicate the receipt of the client's SYN flag in packet #1.
Notice that the acknowledgment number has been increased by 1 although no payload data has yet been sent by the client. This is because the presence of the SYN or FIN flag in a received packet triggers an increase of 1 in the sequence. (This does not interfere with the accounting of payload data, because packets with the SYN or FIN flag set do not carry a payload.)
请注意,尽管客户端尚未发送任何负载数据,但确认编号已增加 1。这是因为收到的数据包中存在 SYN 或 FIN 标志会触发序列中增加 1。(这不会干扰有效负载数据的核算,因为设置了 SYN 或 FIN 标志的数据包不会携带有效负载。
Packet #3
数据包 #3
Like in packet #2, the client responds to the server's sequence number of zero with an acknowledgment number of 1. The client includes its own sequence number of 1 (incremented from zero because of the SYN).
与数据包 #2 中一样,客户端使用确认号 1 响应服务器的序列号 0。客户端包括自己的序列号 1(由于 SYN 的原因,从零开始递增)。
At this point, the sequence number for both hosts is 1. This initial increment of 1 on both hosts' sequence numbers occurs during the establishment of all TCP sessions.
This is the first packet in the stream which carries an actual payload (specifically, the client's HTTP request). The sequence number is left at 1, since no data has been transmitted since the last packet in this stream. The acknowledgment number is also left at 1, since no data has been received from the server, either.
Note that this packet's payload is 725 bytes in length.
请注意,此数据包的有效负载长度为 725 字节。
Packet #5
数据包 #5
This packet is sent by the server solely to acknowledge the data sent by the client in packet #4 while upper layers process the HTTP request. Notice that the acknowledgment number has increased by 725 (the length of the payload in packet #4) to 726; e.g., "I have received 726 bytes so far." The server's sequence number remains at 1.
This packet marks the beginning of the server's HTTP response. Its sequence number is still 1, since none of its packets prior to this one have carried a payload. This packet carries a payload of 1448 bytes.
The sequence number of the client has been increased to 726 because of the last packet it sent. Having received 1448 bytes of data from the server, the client increases its acknowledgment number from 1 to 1449.
For the majority of the capture, we will see this cycle repeat. The client's sequence number will remain steady at 726, because it has no data to transmit beyond the initial 725 byte response. The server's sequence number, in contrast, continues to grow as it sends more segments of the HTTP response.
After acknowledging the last segment of data from the server, the client processes the HTTP response as a whole and decides no further communication is needed. Packet #38 is sent by the client with the FIN flag set. Its acknowledgment number remains the same as in the prior packet (#37).
在确认来自服务器的最后一段数据后,客户端将 HTTP 响应作为一个整体进行处理,并决定不需要进一步的通信。数据包 #38 由设置了 FIN 标志的客户端发送。其确认编号与上一个数据包 (#37) 中的编号相同。
Packet #39
数据包 #39
The server acknowledges the client's desire to terminate the connection by increasing the acknowledgment number by one (similar to what was done in packet #2 to acknowledge the SYN flag) and setting the FIN flag as well.
服务器通过将确认编号增加 1(类似于数据包 #2 中确认 SYN 标志的操作)并设置 FIN 标志来确认客户端终止连接的愿望。
Packet #40
数据包 #40
The client sends its final sequence number of 727, and acknowledges the server's FIN packet by incrementing the acknowledgment number by 1 to 22952.
客户端发送其最终序列号 727,并通过将确认编号增加 1 到 22952 来确认服务器的 FIN 数据包。
At this point, both hosts have terminated the session and can release the software resources dedicated to its maintenance.
假如 A 发送的最后一次 ACK 丢包了,没有被 B 收到,那 B 超时之后,会再次发送一个 FIN 包,然后这个包被处于 TIME_WAIT 状态的 A 收到,A 会再次发送一个 ACK 包,并重新开始计时,一直循环这个过程,直到 A 在 TIME_WAIT 的整个过程中都没有收到 B 发过来的 FIN 包,这说明 B 已经收到了 A 的 ACK 包并 CLOSE 了,因此 A 这时候才可以安心 CLOSE。如果 A 没有 TIME_WAIT 状态而是直接 close,那么当 ACK 丢包之后,B 会再次发送一个 FIN 包,但是这个包不会被 A 回应,因此 B 最终会收到 RST,误以为是连接错误,不符合可靠连接的要求。因此需要等待 ACK 报文到达 B。RST 是 TCP 数据报中 6 个控制位之一,6 个控制位的作用如下:
如果 A 直接 close 了,然后向 B 发起了一个新的 TCP 连接,可能两个连接的端口号相同 。一般不会有什么问题,但是如果旧的连接有一些数据堵塞了,没有到达 B,新的握手连接就已经到 B 了,那么这时候,由于区分不同 TCP 连接是依据套接字,因此 B 会将这批迟到的数据认为是新的连接的数据,导致数据混乱(源 IP 地址和目的 IP 地址以及源端口号和目的端口号的组合称为 套接字,新旧连接的套接字很有可能相同)。如果我们终止一个客户程序,并立即重新启动这个客户程序,则这个新客户程序将不能重用相同的本地端口。服务端处于被动关闭,不会出现该状态。
刚才说到,【当前包的序列号 + 载荷长度 = 下一包序列号】,看到这里可能会有细心读者问,图中 1 号 SYN 包和 7 号 FIN 包并不存在载荷长度,为何下一包序列号被设置为序列号 + 1?
这是由于 SYN 包和 FIN 包为连接中较重要的包,需要被确认,因此数据包的 SYN 位和 FIN 位被 TCP 视为 1 字节的载荷数据。所以,在 TCP 三次握手中,客户端 SYN 和服务器 SYN/ACK 包的下一包序列号为【当前包的序列号(ISN)+ 载荷长度(1 字节 SYN 位)= 下一包序列号(ISN+1)】。如下图所示:
The acknowledgment mechanism employed is cumulative so that an acknowledgment of sequence number X indicates that all octets up to but not including X have been received.
A host that is receiving a stream of TCP data segments can increase efficiency in both the Internet and the hosts by sending fewer than one ACK (acknowledgment) segment per data segment received; this is known as a "delayed ACK" TCP:5.
A TCP SHOULD implement a delayed ACK, but an ACK should not be excessively delayed; in particular, the delay MUST be less than 0.5 seconds, and in a stream of full-sized segments there SHOULD be an ACK for at least every second segment.
每个 TCP 数据包均包含 "win"(窗口大小)和 "ack"(确认号)字段。"win" 字段用于告知对方本机当前还能够接收数据的滑动窗口大小。例如,若 A 发送至 B 的数据包中 "win" 值为 0,则表示 A 向 B 传达当前自身的滑动窗口已无可用空间,无法继续接收数据,这通常暗示 A 端存在一定的环境压力,如网络带宽已被占满等情况。
"ack"(确认号)可以理解为一种应答机制。A 发送给 B 的 "ack" 值,是用于告知 B,A 已经接收到 B 发送的数据包,并且已经处理到了 "ack" 所标识的序号位置,同时指示 B 下次发送数据包时,其 "seq" 值应设置为该 "ack" 号。