首先解释一段截取的网络数据认识一下。(由a_la_lei解释)
1、-> syn(这一步是初始化发送端的ISN。理论上,它的数据字段没有任何值,消耗的是一个虚字节)
TCP: Sequence number = 4071231308
TCP: Acknowledgement number = 0
2、<- ack syn(初始化接收端的ISN,并对收到的包进行确认。因为确认的方式是累计确认,所以尽管第1步传输了一个虚字节,但ACK仍旧是4071231308+1=4071231309)
TCP: Sequence number = 1191340143
TCP: Acknowledgement number = 4071231309
3、-> ack(回应第2步的确认。因为第1步消耗的是一个虚字节,所以理论上Seq应该仍旧是4071231308,但由于协议的具体实现略有不同,这里又在虚字节上加1变成4071231309。仍旧是累计确认。)
TCP: Sequence number = 4071231309
TCP: Acknowledgement number = 1191340144
4、-> ack push 登录信息(载荷包。因为第3步仅是一个确认包,它没有包含任何有效数据,所以这里的Seq仍旧是4071231309。仍旧是对第2步确认)
TCP: Sequence number = 4071231309
TCP: Acknowledgement number = 1191340144
5、<- ack(仅仅是一个确认包。仍旧是根据累计确认原则对第4步确认,ACK等于4071231309+有效载荷=4071231337)
TCP: Sequence number = 1191340144
TCP: Acknowledgement number = 4071231337
6、<- ack push 回应信息(载荷包。因为第5步仅仅是一个确认包,所以这里不消耗任何序号,Seq仍旧是1191340144。ACK仍旧是对第4步的确认)
TCP: Sequence number = 1191340144
TCP: Acknowledgement number = 4071231337
7、-> ack(仅仅是一个确认包。仍旧是根据累计确认原则对第6步确认,ACK等于1191340144+有效载荷=1191340217)
TCP: Sequence number = 4071231337
TCP: Acknowledgement number = 1191340217
8、<- ack push 第二次回应信息(载荷包。因为仍旧有数据要发送,按第7步给予的ACK来设置此包的Seq。此包的Ack仍旧是4071231337)
TCP: Sequence number = 1191340217
TCP: Acknowledgement number = 4071231337
本流程需要知道的几个规则:
规则1、累计确认。接收端对收到的载荷包(数据字段有值的TCP包),回应一个确认包,确认号是所收到包的TCP数据字段最后一个字节+1。
规则2、捎带确认。载荷包必须捎带确认字段。这样可以减少网络流量。
规则3、虚字节。有些数据包(ACK)不携带任何数据,所以不消耗序列号,也就是说仍旧保持不变。