TCP的建立连接的过程就叫握手。在这个过程中,客户端和服务端需要交换三个报文段。下图便是三报文握手的过程:
一开始,服务端首先创建传输控制块TCB,准备接收客户端的连接请求;客户端同样先建立传输控制块TCB,在打算建立TCP连接时便向B发送连接请求报文段,置SYN位为1,选择一个序号seq=x(表示这是个请求连接报文段),需要注意的是在此次握手中不能携带数据(防止有人恶意攻击,在SYN报文中放入大量的数据,然后大量发送,这会让服务器花费很多时间、空间来接收这些报文,导致服务器不能处理正常的连接请求。)
服务端在收到连接请求报文后,若同意连接,则返回一个确认报文,置SYN位为1,ACK位为1,选择一个序号seq=y,确认号为ack=x+1,同样该报文不能携带数据。
客户端收到服务端的确认后,需要再向服务端给出收到确认。置ACK位为1,确认号ack=y+1,序号seq=y,这时TCP连接便已建立。该报文段是可以携带数据的(因为客户端已经知道服务器能接收、发送。)
例如我们要抓取百度的tcp报文,可以先通过ping命令获取百度的地址:
我们得到的百度地址为:110.242.68.4。打开Wireshark选择以太网或者WLAN(视情况而定)进行抓包,然后打开浏览器输入地址访问百度页面,接着进入Wireshark,停止抓包,在上方标签栏输入:
ip.dst eq 110.242.68.4
接着回车便会出现这样的界面:
我们可以看到在前三个TCP报文段便是建立连接时的三次挥手。
下面是第一次握手:
在第一个报文中(上面截图),是客户端向服务端发送请求连接,因此源地址为我的电脑IP:Src:172.16.23.67,目的地址为百度地址:Dst:110.242.68.4,源端口为:60828,目的端口为:80,seq=0,ack=0,SYN置1。
下面是第二次握手:
而第二个报文中(上面截图),是服务端发给客户端的确认报文,因此源地址为百度的IP:Src:110.242.68.4,目的地址为我的电脑IP:Dst:172.16.23.67,源端口为:80,目的端口为:60828,SYN置1,ACK也置1。
下面是第三次握手:
在第三个报文中(上面截图),是客户端向服务端发送请求连接,因此源地址为我的电脑IP:Src:172.16.23.67,目的地址为百度地址:Dst:110.242.68.4,源端口为:60828,目的端口为:80,seq=1,ack=1,SYN置0(如不向报文内添加内容,则不继续消耗序号),ACK置1。
要说明的是,在以上的报文中,我们所看到的seq,ack,全是经过Wireshark处理过的,目的是方便我们理解,实际序号会很混乱。