在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
完成三次握手,客户端与服务器开始传送数据,在上述过程中,还有一些重要的概念:
未连接队列:在三次握手协议中,服务器维护一个未连接队列,该队列为每个客户端的SYN包(syn=j)开设一个条目,该条目表明服务器已收到SYN包,并向客户发出确认,正在等待客户的确认包。这些条目所标识的连接在服务器处于Syn_RECV状态,当服务器收到客户的确认包时,删除该条目,服务器进入ESTABLISHED状态。
Backlog参数:表示未连接队列的最大容纳数目。
SYN-ACK重传次数 服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传,如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。注意,每次重传等待的时间不一定相同。
半连接存活时间:是指半连接队列的条目存活的最长时间,也即服务从收到SYN包到确认这个报文无效的最长时间,该时间值是所有重传请求包的最长等待时间总和。有时我们也称半连接存活时间为Timeout时间、SYN_RECV存活时间。
====================================================================
现在,我们来看一个完整的流程,在一个TCPsocket上系统调用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首部):
数据内容含义
基本首部
800e源端口(32782)
138a目的端口(5002)
00 00 07bc初始序号ISN
00 00 0000确认序号
a首部长度
002标志位,SYN=1
16d0滑动窗口大小(5840)
649e校验和
0000紧急指针
TCP选项
02 04 05b4最大报文段长度(1460)
0402允许SACK
08 0a 00 0a 79 14 00 00 0000时间戳(0x000a7914),回显时间戳(0)
01占位。
03 0302窗口扩大因子(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首部
138a源端口(5002)
800e目的端口(32782)
98 8e 4091初始序号ISN
00 00 07bd确认序号(对端ISN+1)
a首部长度
012标志位,ACK=1, SYN=1
16a0滑动窗口大小
65d7校验和
0000紧急指针
TCP选项
02 04 05b4最大报文段长度(1460)
0402允许SACK
08 0a 00 3c 25 8a 00 0a 7914时间戳(0x003c258a),回显时间戳(000a7914)
01占位
03 0302窗口扩大因子(2)
第三步,172.16.48.2对来自172.16.48.1的SYN段进行确认,至此,TCP三次握手协议完成,连接建立,在172.16.48.2收到SYN段时,将自己对应的socket的状态由TCP_SYN_SENT改为TCP_ESTABLISHED,进入连接建立状态,下面是数据内容:
数据内容含义
800e源端口(32782)
138a目的端口(5002)
00 00 07bd序号(已不是ISN了)
98 8e 4092确认序号(对端ISN+1)
8首部长度(8*4=32,有12字节的选项)
010标志,ACK=1
05b4滑动窗口大小(1460,有问题?待确认)
a58a校验和
0000紧急指针
01占位
01占位
08 0a 00 0a 79 14 00 3c 258a时间戳(0x0a007914), 回显时间戳(0x003c258a)
=====================================================================
7、简述TCP三次握手过程,并说明为什么要3次握手
TCP 三次握手
TCP 连接是通过三次握手进行初始化的。三次握手的目的是同步连接双方的序列号和确认号并交换 TCP窗口大小信息。以下步骤概述了通常情况下客户端计算机联系服务器计算机的过程:
1.客户端向服务器发送一个SYN置位的TCP报文,其中包含连接的初始序列号x和一个窗口大小(表示客户端上用来存储从服务器发送来的传入段的缓冲区的大小)。
2.服务器收到客户端发送过来的SYN报文后,向客户端发送一个SYN和ACK都置位的TCP报文,其中包含它选择的初始序列号y、对客户端的序列号的确认x+1和一个窗口大小(表示服务器上用来存储从客户端发送来的传入段的缓冲区的大小)。
3..客户端接收到服务器端返回的SYN+ACK报文后,向服务器端返回一个确认号y+1和序号x+1的ACK报文,一个标准的TCP连接完成。
TCP 使用类似的握手过程来结束连接。这可确保两个主机均能完成传输并确保所有的数据均得以接收
TCP Client Flags TCP Server
1 Send SYN (seq=x) ----SYN---> SYNReceived
2 SYN/ACK Received <---SYN/ACK----Send SYN (seq=y), ACK(x+1)
3 Send ACK (y+1) ----ACK---> ACK Received,Connection Established
w: ISN (Initial Sequence Number) of theClient
x: ISN of the Server
==========================================================
握手阶段:
序号 方向 seqack
1 A->B100000
2B->A2000010000+1=10001
3A->B1000120000+1=20001
解释:
1:A向B发起连接请求,以一个随机数初始化A的seq,这里假设为10000,此时ACK=0
2:B收到A的连接请求后,也以一个随机数初始化B的seq,这里假设为20000,意思是:你的请求我已收到,我这方的数据流就从这个数开始。B的ACK是A的seq加1,即10000+1=10001
3:A收到B的回复后,它的seq是它的上个请求的seq加1,即10000+1=10001,意思也是:你的回复我收到了,我这方的数据流就从这个数开始。A此时的ACK是B的seq加1,即20000+1=20001
数据传输阶段:
序号 方向 seqacksize
23A->B40000700001514
24B->A7000040000+1514-54=4146054
25A->B4146070000+54-54=700001514
26B->A7000041460+1514-54=4292054
解释:
23:B接收到A发来的seq=40000,ack=30000,size=1514的数据包
24:于是B向A也发一个数据包,告诉B,你的上个包我收到了。B的seq就以它收到的数据包的ACK填充,ACK是它收到的数据包的SEQ加上数据包的大小(不包括以太网协议头,IP头,TCP头),以证实B发过来的数据全收到了。
25:A在收到B发过来的seq为41460的数据包时,一看到41460,正好是它的上个数据包的seq加上包的大小,就明白,上次发送的数据包已安全到达。于是它再发一个数据包给B。这个正在发送的数据包的seq也以它收到的数据包的ACK填充,ACK就以它收到的数据包的seq(70000)加上包的size(54)填充,即ack=70000+54-54(全是头长,没数据项)。
26:一样的啊
TCP 三次握手的意义在哪里?
最好详细点,考虑全面。
我能想到的:
1.用较短的SYN包来探测目的主机端口及中间网络是否工作
2.初始化序列号
问题:TCP为什么要使用随机初始序列号?
我看过解释是防止连接失效后SOCKET被重用使得以前残留的包被错误的接受。但是现在主机刚刚释放的SOCKET不都是不可马上使用的么?
3.同步MSS
请各位补充。
1.我认为你说对了一方面,,,还有一方面就是,,,让server为client预留一部分服务器资源,,,需要注意的是,,,正是因为这样,,,就有了大家都知道的Dos(Denialof service)以及衍生出来的DDos(DistributedDos),,,后者更为可怕和难易分析监测,,,其原理就是,,,向server发出syn,,,然后呢,,,又不跟server进行进一步的通信,,,这样,,,就导致server为它白白的分配了很多资源,,,我们可以想想的是,,,当这种syn达到一定数量以后,,,server肯定会爆掉,,,这种攻击相当之恐怖,,,传说累计有几百亿美元的损失了吧,,,同时,,,这也是当今网络安全研究的一个热点,,,
2.首先,我觉得你思考倒要用随机序列号这个问题很厉害,,,
应该是这样的,,,这个是处于网络安全的角度来做的,,,如果没有随机生成tcp的序列号的话,,,hacker们就可以轻易的采取某些手段猜测到你和别人通信的tcp序列号,,,并且制造tcp序列号攻击,,,这已经是当今网络上一种常见的攻击,,,tcp当时的设计者并没有考虑到这些,,,即便是这样,,,tcp序列号攻击也是有办法进行的,,,就为了防止这种攻击,,,已经有很多tcp序列号的生成算法被提出和改进,,,你可以倒ieee上面去搜下,,,较多,,,据我所知,,,unix这方面做的比windows好