让我们创建tcp连接建立,http请求和响应以及tcp连接终止的整个过程。
/var/www/html/phplearn/send.php
<form action="http://127.0.0.1/phplearn/do.php" method="post">
name: <input type="text" name="userName" size="12"/>
key: <input type="text" name="PS" size="12"/>
<input type="submit" value="login">
</form>
/var/www/html/phplearn/do.php
<?php
$userName = $_POST["userName"];
$PS = $_POST["PS"];
echo "the name is: ".$userName;
echo "<br>key word is: ".$PS;
?>
使用以下参数打开tcpdump:
sudo tcpdump -i lo host 127.0.0.1 -w /tmp/dataDst.pcap
使用curl发送信息
curl -d“userName = test&amp; PS = test_pass”127.0.0.1/phplearn/do.php
使用wireshark打开/tmp/dataDst.pcap
Process1:tcp连接建立。
从1号到3号,没问题。
Process2:http请求和响应
no5客户端在服务器
上从端口38219向80发送http请求
no6服务器向客户端发送tcp信号
no7服务器向客户端发送http响应
Process3:tcp连接终止
从tcpdump观察到的tcp连接终止过程与web上的图完全不同。
在我的观察中,
no7从客户端在端口38219到服务器端口80 ACK
客户端38219上的no8到服务器端口80 FIN
从服务器端口80到端口38219 FIN上的客户端的no9
从端口38219上的客户端到服务器端口80确认的no10
从图中可以看出,客户端到服务器有两个tcp包,服务器到客户端有两个tcp包。
从我的tcpdump,从客户端到服务器有三个tcp包,从服务器到客户端只有一个tcp包。
您能否详细解释我的观察与序列图之间差异的原因?
答案 0 :(得分:1)
在数据包7 中,客户端确认收到HTTP 来自服务器的响应OK数据包。这在TCP连接关闭序列图中没有描述,因为它不属于它,而是属于正常的TCP传输。
然后客户端在数据包8 中指示它要关闭
连接。请注意,虽然在此数据包中设置了ACK
- 标志,但由于ACK
- 数字的值相同(194
),因此不会确认收到任何新数据。使用数据包7进行检查。ACK
- 数字的值也是194
。此步骤对应于图表的第一个箭头。
在数据包9 中,服务器确认关闭指示 客户并告诉客户,它也想终止他的一方 连接。此步骤对应于从服务器到图形客户端的两个箭头。您的服务器将其打包在一个数据包中,与发送两个数据包相比,这样可以保存数据。
在数据包10 中,客户端确认服务器也想要 终止他的部分连接和连接是 因此双方都关闭了。此步骤对应于图表的最后一个箭头。
这完全遵循您在问题中嵌入的序列图,但ACK
- 数据包与FIN
- 数据包一起发送
请注意,TCP是bidirektional,因此客户端可以发送到服务器,服务器可以通过相同的连接对此进行响应。但它也允许半封闭连接。这意味着,虽然客户端在数据包8中指示他不想再发送,但他仍然可以从服务器接收数据。 但是由于服务器不想再发送数据,他还通过数据包9中的FIN数据包来指示这一点。我告诉你这可能是因为你可能想知道,为什么服务器还需要向客户端发送一个FIN数据包
有关TCP连接状态模型的有用且更详细的图形可以在Tanenbaum p中找到。 532或它也在苏黎世联邦理工学院lecture slides上描绘。