TCP实验
实验步骤
1、打开Wireshark软件捕捉数据包,在浏览器中访问网站,比如学校官网(IP地址为211.83.176.232)
2、在Wireshark中使用过滤器过滤出tcp包,再选择某一个客户端端口,过滤,只查看这个端口与服务器之间的通信。
3、分析数据包内容,以及通信过程。
理论
tcp报文首部格式
接下来要着重分析的是序号,确认号,以及falg标志字段(URG、AKC、、、)
序号字段:占 4 字节。TCP 连接中传送的数据流中的每一个字节都编上一个序号。序号字段的值则指的是本报文段所发送的数据的第一个字节的序号。
确认号字段:占 4 字节,是期望收到对方的下一个报文段的数据的第一个字节的序号,也就是当前收到报文的最后一个字节的序号+1。 (也可以说是对刚才收到的报文进行确认,如果刚才收到的报文中的序号字段为seq=x,数据部分有n个字节,那么对这个报文的进行确认的报文的确认号字段就要为ack=x+n+1)
标志字段各部分含义:
- 确认 ACK:只有当 ACK = 1 时确认号字段才有效。当 ACK = 0 时,确认号无效。
- 推送 PSH (PuSH) :接收 TCP 收到 PSH = 1 的报文段,就尽快地交付接收应用进程,而不再等到整个缓存都填满了后再向上交付。
- 复位 RST (ReSeT) :当 RST = 1 时,表明 TCP 连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。
- 同步 SYN :同步 SYN = 1 表示这是一个连接请求或连接接受报文。
- 终止 FIN (FINish) :用来释放一个连接。FIN = 1 表明此报文段的发送端的数据已发送完毕,并要求释放运输连接。
tcp建立连接的三报文握手
注意:
- SYN是标志字段中的同步SYN,为1时表示这个报文是连接请求,或接受连接。
- seq是首部中的序号字段,发送方为发送的每一个字节都编上一个序号,序号字段的值则指的是本报文段所发送的数据的第一个字节的序号。由于tcp在进行建立连接或释放连接时,数据部分都为空(seq是数据部分的第一个字节,也是整个报文的最后一个字节),所以如果接收方接收到一个序号为seq=x的报文,那么要对其进行确认的报文的确认号字段就应该为ack=x+1)
- 客户端与服务器所发送的seq之间是没有必然联系的,它们所发送的seq的值只取决于自己发送的字节数的多少。
- 但发送方所发送的ack却与刚才收到的seq有关,关系为发送方要发送的ack=刚才收到的报文的seq+刚才收到的报文的数据部分的字节数+1
tcp释放连接的四报文握手
当客户端请求释放连接,并收到服务端的同意后,客户端不能再发送数据,但仍然需要接受数据。服务端既可以发送数据,也可以接受数据(实际上由于客户端不在发送数据了,所以服务器端是收不到的)
实验过程
打开Wireshark捕捉数据包,再打开浏览器访问学校官网(211.83.176.232),官网界面加载出来后关闭浏览器,以免数据太多找不到TCP的FIN释放连接。
对捕获到的结果使用过滤器ip.addr==211.83.176.232 and tcp.port == 59845
进行过滤,结果如下:
再捕获结果中443是服务器端口,是固定的,59845是客户端的端口,是我从多个端口中选择的一个。为方便表示,下面使用45和43分别表示客户端和服务器。
建立连接
分析前几行的数据包,观察tcp建立连接的过程。
与tcp连接建立的示意图相匹配
45向43请求建立连接的数据包内容
43同意45建立连接的请求的数据包的内容
这里的相对序号可能说的是对于45与43之间通信的序号吧,计算机一旦联网肯定会同时产生很多的tcp数据,为了方便分析,所以这里可能就使用这样的相对序号。
传输数据
关于序号与确认号之间的关系,截取数据传输过程中的一对数据包进行分析
43给45发送一个数据包(记为数据包A),seq=14819,len=1400,也就是说,数据部分是从14819到14819+1400-1=16218之间。所以这个报文的最后一个字节的编号为为16218,数据包A的ACK=1335,说明它希望下一个收到的数据包的seq=1335,也就是数据部分的第一个字节的编号为1335。
45个43发送一个数据包(记为数据包B),seq=1335,刚好就是数据包A所期望收到的。ACK=16219,说明它期望收到的下一个数据包的seq=16219,(也可以理解为是对数据包A的确认),因为数据包A的最后一个字节的编号是16218,如果43还要发送一个数据包,那么这个数据包的编号就应该从16219开始编号。
上图中,43给45发送了很多数据,而45也给43发送数据进行了确认,但为什么43发送的数据的AKC都是1335呢?
因为45虽然给45发送了数据确认,但数据包中只有首部,数据部分为空,而seq的编号是对tcp的数据部分进行编号,数据部分的长度len一直为0,那么无论发送多少个数据包,编号都不会变,所以45的seq一直保持为1335,它既是当前包的数据部分的最后一个字节的编号,也是下一个包的数据部分的第一个字节的编号(seq)。43期望收到45的编号为1335的字节的数据,但由于45一直没有发送数据(数据部分为空),所以43的下一个包也是期望收到1335(ACK=1335)。
当45给43发送数据后,45的seq就变了,43的ACK也随之改变。从上图中的超时的数据包可以看出,45发送了769字节的数据,所以45发送的最后一个字节的编号由原来的1334变为了现在的2103,(1334+769或1335+769-1)。接下来,43期望收到的就是从2104开始的数据了(ACK=2104)。
释放连接
这里释放连接时倒是和示意图有些不同,可以是由于服务端没有数据需要继续传送了,所以就将第2步和第3步合并成了一步,服务器对释放连接的请求进行确认的同时也将自己的连接释放。
123