现在,我们来看一个完整的流程,在一个TCP socket上系统调用connect究竟是如何建立起一个到对端的连接的。我们还是以实验环境172.16.48.2向172.16.48.1的端口5002发起连接请求为例。
第一步,172.16.48.2向172.16.48.1发起连接请求,发送一个SYN段,指明目的端口5002,通告自己的初始序号(ISN,由协议栈
随机产生的一个32位数),设置确认序号为0(因为还没有收到过对端的数据),通告自己的滑动窗口大小为5840(对端是5792,这似乎有问题,有待进
一步细查),窗口扩大因子为2(在首部选项中),通告最大报文段长度为1460(本地局域网),下面是数据内容(已剥去链路层的以太网首部和网络层的IP
首部):
数据内容 含义
基本首部
80 0e 源端口(32782)
13 8a 目的端口(5002)
00 00 07 bc 初始序号ISN
00 00 00 00 确认序号
a 首部长度
0 02 标志位,SYN=1
16 d0 滑动窗口大小(5840)
64 9e 校验和
00 00 紧急指针
TCP选项
02 04 05 b4 最大报文段长度(1460)
04 02 允许SACK
08 0a 00 0a 79 14 00 00 00 00 时间戳(0x000a7914),回显时间戳(0)
01 占位。
03 03 02 窗口扩大因子(2)
第二步,172.16.48.1收到请求包,检查标志位,发现SYN=1,认为这是一个初始化连接的请求,回应这个SYN,同时也发送自己的SYN段(即
ACK,SYN同时置位)。因为SYN本身要占用一个序号(还有标志FIN也要占用一个序号)。所以,确认序号设置为172.16.48.2的ISN加
1(即172.16.48.1期望收到来自172.16.48.2的下一个包的第一个序号为0x07bd。同时也要通告自己的初始序号,滑动窗口大小,窗
口扩大因子,最大报文段长度等,下面是数据内容:
数据内容 含义
基本TCP首部
13 8a 源端口(5002)
80 0e 目的端口(32782)
98 8e 40 91 初始序号ISN
00 00 07 bd 确认序号(对端ISN+1)
a 首部长度
0 12 标志位,ACK=1, SYN=1
16 a0 滑动窗口大小
65 d7 校验和
00 00 紧急指针
TCP选项
02 04 05 b4 最大报文段长度(1460)
04 02 允许SACK
08 0a 00 3c 25 8a 00 0a 79 14 时间戳(0x003c258a),回显时间戳(000a7914)
01 占位
03 03 02 窗口扩大因子(2)
第三步,172.16.48.2对来自172.16.48.1的SYN段进行确认,至此,TCP三次握手协议完成,连接建立,在172.16.48.2收
到SYN段时,将自己对应的socket的状态由TCP_SYN_SENT改为TCP_ESTABLISHED,进入连接建立状态,下面是数据内容:
数据内容 含义
80 0e 源端口(32782)
13 8a 目的端口(5002)
00 00 07 bd 序号(已不是ISN了)
98 8e 40 92 确认序号(对端ISN+1)
8 首部长度(8*4=32,有12字节的选项)
0 10 标志,ACK=1
05 b4 滑动窗口大小(1460,有问题?待确认)
a5 8a 校验和
00 00 紧急指针
01 占位
01 占位
08 0a 00 0a 79 14 00 3c 25 8a 时间戳(0x0a007914), 回显时间戳(0x003c258a)
阅读(163) | 评论(0) | 转发(0) |