在开始介绍TCP连接之前,先来看看TCP数据包的首部,首部里面有很多重要的字段,在我们实现程序的时候需要进行设置。
TCP的首部
在OSI七层模型中,上层的数据包都会作为下层数据包的数据部分(payload)。
也就是说,当构造TCP数据包的时候,会把应用层的数据包作为TCP包的数据部分,然后加上TCP头构成TCP数据包;同样,当构造IP数据包的时候,整个TCP包就会被当作数据部分,然后加上IP头构成IP数据包。
TCP头的数据格式如下,在不包括可选字段的情况下,一般TCP头会占用20个字节。
在TCP首部中,有几个字段是需要关注一下:
在TCP首部中没有源和目标的IP、MAC地址(IP和MAC地址分别是网络层和链路层首部的信息),只有源和目标的端口
Sequence Number是包的序号,网络层(IP层)的传输是不可靠的,可能产生包乱序,所以这个需要可以解决网络包乱序的问题
Acknowledgement Number用来确认收到数据包的确认序号,为TCP的传输提供了可靠性保证
TCP Flags包括了8个bit,通过对这些bit的设置,可以代表不同类型的TCP数据包
下面就看看TCP连接的建立和终止。
TCP连接建立
TCP连接建立的过程被称为三次握手过程:
连接建立发起端发送[SYN]包,该端将主动打开(active open)
接收端将发送[SYN, ACK]包,该端将被动打开(passive open),ACK标志表示对收到的[SYN]包的确认
连接建立发起端发送[ACK]包确认[SYN, ACK]包
Initial Sequence Number
连接建立过程中,一个重要的工作就是初始化Sequence Number,通信的双方在建立连接的过程中互相通知对方自己的初始Sequence Number(ISN:Initial Sequence Number)。ISN不是固定的,ISN跟时钟绑定,根据特定的间隔自增,直到超过2^32,又从0开始。
SYN全称就是Synchronize Sequence Number,通过seq序号,TCP就可以保证数据包的顺序;通过ack序号,TCP就有了可靠性。
连接建立注意点
在建立TCP连接的过程中,有以下两点需要注意一下:
[SYN]标志的数据包会使用消耗一个序号,所以对端的确认号(ack)是当前序号(seq)加一
当被动打开端发送[ACK]确认包的时候,同时设置了[SYN]标志,所以TCP连接建立的过程只需要三次握手,而不是四次
TCP连接终止
TCP连接终止的过程被称为四次挥手过程,以下图为例:
连接终止端(client)发送[FIN, ACK] 包,关闭client到server方向的数据发送通路
server端发送[ACK]包来确认来自client的[FIN, ACK] 包
server端发送[FIN, ACK] 包,关闭server到client方向的数据发送通路
client端发送[ACK]包来确认来自server的[FIN, ACK] 包,到此TCP连接关闭
连接终止注意点
在建立TCP连接的过程中,有以下两点需要注意一下:
[FIN]标志的数据包会使用消耗一个序号,所以对端的确认号(ack)是当前序号(seq)加一
与建立连接时的三次 握手不同,终止连接需要四次挥手
因为TCP连接是全双工的,每个方向都必须单独进行关闭。当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,但是TCP连接在收到一个FIN后仍能发送数据
TCP连接实验
好了,了解了TCP连接建立和终止的基本知识后,就可以通过Pcap.Net来进行TCP连接建立和终止的实验了。
建立连接代码的基本流程如下:
client程序使用一个初始的seq序号(100),然后生成并发送一个带[SYN]标志的TCP包
client将期待来自服务端的[SYN, ACK]包
当收到[SYN, ACK]包之后,client需要生成并发送一个[ACK]包进行确认,这个[ACK]包的ack号是[SYN, ACK]包seq号加一
终止连接代码的基本流程如下:
client程序delay 10秒钟,然后发送[FIN, ACK]包关闭client到server的通路,继续使用全局的seq号
client将期待来自服务端的[ACK]包,以及[FIN, ACK]包
最后client发送[ACK]包,seq号需要加一,因为[FIN]标志的包将消耗一个序号,TCP连接终止完成
主程序如下,发送TCP连接建立和终止请求,每个请求发送后都用PacketHandler处理收到的包:
communicator.SendPacket(Utils.BuildTcpPacket(endPointInfo, TcpControlBits.Synchronize, null)); PacketHandler(communicator, endPointInfo); // delay 10 secs, then client to send Fin Thread.Sleep(10000); communicator.SendPacket(Utils.BuildTcpPacket(endPointInfo, TcpControlBits.Fin | TcpControlBits.Acknowledgment)); PacketHandler(communicator, endPointInfo);
程序的主要逻辑在PacketHandler中,这个函数根据收到的不同TCP包的类型完成不同的逻辑,产生并发送不同类型的包。
例如,当PacketHandler接收到来自服务端的[SYN, ACK]包后,处理函数就会生成并发送一个[ACK]确认包。也就是说,PacketHandler的逻辑就是实现了TCP连接建立和终止的逻辑。
private static void PacketHandler(PacketCommunicator communicator, EndPointInfo endPointInfo) { Packet packet = null; bool running = true; do { PacketCommunicatorReceiveResult result = communicator.ReceivePacket(out packet); switch (result) { case PacketCommunicatorReceiveResult.Timeout: // Timeout elapsed continue; case PacketCommunicatorReceiveResult.Ok: bool isRecvedPacket = (packet.Ethernet.IpV4.Destination.ToString() == endPointInfo.SourceIp) ? true : false; if (isRecvedPacket) { switch (packet.Ethernet.IpV4.Tcp.ControlBits) { case (TcpControlBits.Synchronize | TcpControlBits.Acknowledgment): Utils.PacketInfoPrinter(packet); Packet ack4SynAck = Utils.BuildTcpResponsePacket(packet, TcpControlBits.Acknowledgment); communicator.SendPacket(ack4SynAck); break; case (TcpControlBits.Fin | TcpControlBits.Acknowledgment): Utils.PacketInfoPrinter(packet); Packet ack4FinAck = Utils.BuildTcpResponsePacket(packet, TcpControlBits.Acknowledgment); communicator.SendPacket(ack4FinAck); break; case TcpControlBits.Acknowledgment: Utils.PacketInfoPrinter(packet); break; default: Utils.PacketInfoPrinter(packet); break; } } else { switch (packet.Ethernet.IpV4.Tcp.ControlBits) { case (TcpControlBits.Fin | TcpControlBits.Acknowledgment): Utils.PacketInfoPrinter(packet); break; case TcpControlBits.Synchronize: Utils.PacketInfoPrinter(packet); break; case TcpControlBits.Acknowledgment: Utils.PacketInfoPrinter(packet); running = false; break; default: Utils.PacketInfoPrinter(packet); break; } } break; default: throw new InvalidOperationException("The result " + result + " should never be reached here"); } } while (running); }
在PacketHandler函数中用到了BuildTcpResponsePacket这个函数,这个函数根据收到的TCP包,来构建response包。
这个函数有下面几个注意点:
该函数会根据收到的包,设置response包的源和目的地址
该函数会接受PacketHandler传递来的TCP flags,并设置到TCP首部中
该函数的另一个重要部分就是会计算并设置TCP首部中的seq好ack号,这一点很重要
public static Packet BuildTcpResponsePacket(Packet packet, TcpControlBits tcpControlBits) { EthernetLayer ethernetHeader = new EthernetLayer { Source = new MacAddress(packet.Ethernet.Destination.ToString()), Destination = new MacAddress(packet.Ethernet.Source.ToString()), EtherType = EthernetType.None, // Will be filled automatically. }; IpV4Layer ipHeader = new IpV4Layer { Source = new IpV4Address(packet.Ethernet.IpV4.Destination.ToString()), CurrentDestination = new IpV4Address(packet.Ethernet.IpV4.Source.ToString()), Fragmentation = IpV4Fragmentation.None, HeaderChecksum = null, // Will be filled automatically. Identification = 123, Options = IpV4Options.None, Protocol = null, // Will be filled automatically. Ttl = 100, TypeOfService = 0, }; TcpLayer tcpHeader = new TcpLayer { SourcePort = packet.Ethernet.IpV4.Tcp.DestinationPort, DestinationPort = packet.Ethernet.IpV4.Tcp.SourcePort, Checksum = null, // Will be filled automatically. SequenceNumber = seqNum = packet.Ethernet.IpV4.Tcp.AcknowledgmentNumber, AcknowledgmentNumber = ackNum = packet.Ethernet.IpV4.Tcp.SequenceNumber + (uint)((packet.Ethernet.IpV4.Tcp.Payload.Length > 0) ? packet.Ethernet.IpV4.Tcp.Payload.Length : 1), ControlBits = tcpControlBits, Window = windowSize, UrgentPointer = 0, Options = TcpOptions.None, }; PacketBuilder builder = new PacketBuilder(ethernetHeader, ipHeader, tcpHeader); return builder.Build(DateTime.Now); }
运行效果
打开Wireshark监听"VirtualBox Host-Only Network"网卡,并设置filter为"port 8081"。
然后运行程序,通过console可以看到客户端发送的包,以及服务端返回的包,通过这些包完成了TCP连接的建立和终止。
下面是Wireshark中显示的结果,Wireshark比较友好,会显示相对seq号,所以看到的都是从0开始编号。
注意seq号和ack号的变化,[SYN]和[FIN]标志的TCP包都会消耗一个序号。
总结
本文介绍了TCP首部,通过设置TCP首部中的[SYN]标志,可以构造TCP连接建立请求包;通过设置[FIN]标志,可以构造TCP连接终止请求包。
文中使用Pcap.Net构建了一个简单的客户端,完成了向服务器建立(三次握手)和终止(四次挥手)连接的过程。
通过这个实验,一定会对TCP连接的建立和终止有一个比较直观的认识。
TCP连接的建立和终止 详解
TCP的连接和终止
TCP是一个面向连接的协议。在传输数据前必须要建立连接,在停止传输数据后要终止连接释放资源。
一.TCP连接建立
TCP连接是在IP网络中两个进程间(应用层协议)的双向、全双工的逻辑回路。由节点的IP地址和端口将连接双方对应起来。
1.TCP连接特点:
通过一个握手进程建立起来;
通过一个周期性保持进程来保持,保证两个TCP节点间处于激活状态;
通过一个握手进程来终止,释放资源。
TCP连接也被连接中的任意一端重置。
1.TCP连接的建立
为了建立连接TCP连接双方必须从对方了解下面的信息:
1.对方数据发送的开始序列号;
2.对方在出站管道上发送数据的缓冲区大小;
3.能被接收的最大段MSS;
4.被支持的TCP选项;
通过3个TCP段的交换来了解这些信息,就是常说的TCP 握手的3个包。一般在客户端访问TCP服务器的时候,在客户端初始化一个TCP连接,服务器端打开一个特殊端口等待传入的请求。客户端主动发起第一个 SYN置位的包开始协商TCP连接。服务器接收后向客户端回ACK,最后客户端在向服务器回复ACK后连接建立。
下面我们用TCP连接的两个对等端A和B来详细介绍握手过程,其中发起方是A。
TCP 连接建立进程的3个TCP段交换
段一:同步(SYN)段
TCP连接的发起方A向B发送第一个TCP同步段(SYN).在TCP头部的选项中会包含一些选项与对端协商。
TCP 头部包含如下字段:
目的端口 TCP连接对端B被动打开的TCP端口数
源端口 TCP连接发起方A主动打开的端口,大多数是一个随机一个端口。
序列号 SYN的序列号ISN1可以看作是一个32位的计数器,由发起方A产生,具有一定的随机性。Windows 2003和XP根据派生启动(startup-derived)、2048位的随机密钥和一个基于RC4的随机数来计算ISN,从而减少下一TCP连接的 ISN被预测的可能性。
确认号 设置为0.SYN握手第一个包的ACK字段不重要,此时刚发起连接没有数据报需要确认。但后续的ACK是重要的。
SYN标志 置1.
窗口 设置为默认值,指示本地TCP接收缓冲区大小的初始值。
MSS TCP选项中的MSS 指示发起方A接收的最大的TCP段。
选择性确认(SACK) ?TCP选项 如果包含这个字段,可以指示发起方A 的TCP能接收和解释此选项。
窗口缩放选项 如果包含,指示出发起方A的TCP能接收和支持此选项。协商好窗口因子后此连接就固定使用直到断开连接
一个FTP会话的SYN段
段二:SYN-ACK段
在B收到SYN包后,B将发SYN-ACK,TCP选项仅包含发起方A发送的SYN包中的的选项。
目的端口 设置为A的源端口
源端口 设置为B端口
序列号 B产生自己的序列号ISN2。和A发送的SYN中的ISN没有关系,仅产生的方法一样。
确认号 期望收到的对端的下一个字节ISN1+1.
SYN标志 置1.
ACK标志 置1,必须有此标志,除了SYN中置0外,SYN之后的所有报文(包括SYN-ACK和实际数据包都会带ACK的标志)。
窗口 设置B可以接收的最大窗口值,一般根据应用程序或者操作系统默认指定。
MSS TCP选项 设为B能接收的最大长度的TCP段;
SACK-许可 如果A发送的SYN包含此选项时才使用此选项,表示B的TCP能接收和解释SACK选项。
窗口缩放选项 如果SYN包含,此时才会包含。
一个FTP会话的SYN-ACK段
段3:ACK段
在TCP连接的发起方A收到SYN-ACK后,A再向B发送ACK。ACK中确认被发起方A使用的最终TCP参数,同时向B确认它该使用同样的参数。自此TCP连接建立完成。
一个FTP会话的SYN-ACK段
2.同时打开
两个应用程序同时执行主动建立TCP的连接的可能性是存在的,此时发送到SYN建立需要交换4个包,如图所示:
同时打开报文交换
需要注意的是,即使同时打开仍然只建立一条连接。(但其他的协议不一定)
3.TCP 连接的结果
1.每一个TCP对等端知道连接上对方将被发送的第一个字节的序列号(发给对方的确认号,A发给B的确认号就是B将发送的序列号,同样B也是。)
2.每一个TCP对等端知道连接上能发送的MSS。选取握手阶段SYN和SYN+ACK包中MSS选项中较小的值。以此值开始进行PMTU的发现机制。
3.知道连接对端接收缓冲区大小,即窗口大小。
4.每个对等端知道对方能否使用SACK,窗口缩放等选项。
4.Windows控制TCP建立连接进程的注册表:
TcpMaxConnectRetransmissions
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:0~255
Default value:2
Present by default:No
设定当试图建立一个TCP连接时,会重传多少次SYN。每次间隔时间加倍。初始的RTO为3秒,并且默认值为2,这样第一次SYN等待3秒后重传第一次,在等待6秒后重传第二次,在等待12秒没有SYN+ACK就超时了。
TcpNumConnections
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:0~0xFFFFFF
Default value:0xFFFFFF
Present by default:No
设定能打开的TCP最大数。默认能打开16777214(0xFFFFFF)个连接。
5.TCP半开连接
TCP 半开连接是未完成的连接建立的进程的一个TCP连接,收到一个SYN包,并且一个SYN-ACK已经发送,但是最后的ACK没有收到。前面知道XP默认设置情况下在发送2个重传SYN-ACK后等待12秒后放弃连接,并释放内存和连接的内部表项,从收到SYN到释放总共会花费21秒。
SYN-ACK重传输的一个半开连接
SYN攻击
SYN攻击就是利用这种方法,使用伪装的IP地址和TCP端口,在短时间内制造大量的半开连接来耗尽资源,造成拒绝服务攻击。大量的半开连接能做如下事情:
1.使用所有可用的内存,
2.使用在TCP传输控制模块(TCB)中所有可能的项,这是一个用来跟踪TCP连接的内部表,一旦半开连接使用完所有的项,就用一个TCP连接复位来响应下一个连接企图。
3.使用所有可能的半开连接,此后用一个TCP连接复位响应下一个连接企图。
可以使用netstat -n -p tcp 查看TCP连接状态,包括半开连接。如果state出现大量的SYN-RECEIVED就该受到SYN攻击了。
Windows xp和2003 在检测和防护SYN攻击方面的注册表:
TcpMaxConnectResponseRetransmissions
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:0~255
Default value:2
Present by default:No
设定针对半开连接的一个AYN-ACK的重传数目,对于大于1的值使用SYN攻击防护机制。
SynAttackProtect
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:0~1
Default value:0
Present by default:No
设置为0禁用SYN攻击防护,1启用SYN攻击防护。被启用时,检测到SYN攻击,则半开连接的超时会更快些。
TcpMaxHalfOpen
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:100~65535
Default value:100 for windows xp 和Windows 2003 web版及标准版,500 for Windows 2003 企业版和数据中心版
Present by default:No
在SYN攻击防护起作用前,此键值设定了在SYN-RECEIVED状态中的TCP链接最大数。
TcpMaxHalfOpenRetried
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:80~65535
Default value:80 for windows xp 和Windows 2003 web版及标准版,400 for Windows 2003 企业版和数据中心版
Present by default:No
在SYN-RECEIVED状态中设定TCP连接的最大数并且在SYN攻击防护起作用前至少发送过一个重传。
6.TCP连接的维持
在建立TCP连接后,必须有一些机制维持TCP连接。如果TCP建立连接后不传输任何数据也没有应用级别的保活机制时,那么TCP连接一直存在,数天,数月会一直存在。中间的路由器可能重启,崩溃,TCP连接的双方无从知道,许多时候一个服务器希望知道客户主机是否崩溃并关机或者崩溃又重新启动。许多实现提供的保活定时器可以提供这种能力。但这个规范并不推荐,理由如下:
在出现短暂差错的情况下,这可能会使一个非常好的连接释放掉;
它们耗费不必要的带宽;
在按分组计费的情况下会在互联网上花掉更多的钱。
TCP保活定时器(keepalive)
Windows 中TCP通过一个TCP keepalive的周期性交换,能维持一个TCP连接。在keepalive的TCP头部序列号字段被设为比当前出站数据流的序列号小1的值。如果一个 TCP对等端的下一个数据的字节序列号是N,那么keepalive的序列号是N-1.
在接收到keepalive包后,对等端回送一个ACK字段,并将确认号置为下一个期望收到的字节N,这个交换证实了两个对等端仍然处于TCP连接状态中。
Windows 2003 和 XP的TCP/IP在默认情况下禁用TCP的keepalive.启用情况下每2个小时发送一次keepalive。如果其他上层协议的保活机制时间小于keepalive,tcp的keepalive将不会发送。
相关注册表
KeepAliveTime
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:0~0xFFFFFFFF
Default value:0x6DDD00 (2小时)
Present by default:No
如果连接上没有没有数据,并且启用keepalive,此键值在每一个TCP保持活跃包之间设置了毫秒数,默认是2小时。
KeepAliveInterval
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:0~0xFFFFFFFF
Default value:0x3E8 (1000毫秒)
Present by default:No
在没有接收到对初始的保持活跃的响应时,此键值设置了重传时间默认是1秒。重传数目受TcpMaxDataRetransmission键值控制,默认是5.此时的重传不会有指数级的回退行为。
如果都启用且是默认,无数据传输的TCP连接在keepalive包发出后2小时6秒收不到ACK就放弃连接。
举例:
另一端崩溃
keepalive机制在重复发送探测包到一定次数后报错,由TCP转换为“连接超时”
另一端崩溃而重启
客户端telnet到服务器后,我们拔掉服务器网线重启服务器,服务器重启好后我们在telnet客户端上输入命令。服务器重启后丢失了以前连接的所有信息,此时服务器收到来着telnet客户端的命令,不知道此连接的信息,于是TCP就以复位作为应答来结束TCP连接。
另外一端不可达
拔掉网线,模拟中间路由器崩溃,keepalive探测的时候会引起ICMP差错“不可达--没有到达主机的路由”反馈给主机。
二.TCP连接的终止
TCP的连接终止需要4个包交换来完成。在两个逻辑管道上每个逻辑管道上发送方发送FIN置位的终止包,然后收到ACK后关闭该逻辑管道的连接。
TCP连接终止的4个TCP段交换过程
段1:来自TCP对等端A的FIN-ACK
一个期望终止出站数据流的TCP对等端(A)发送一个不包含任何数据的TCP段,他具有如下特点:
序列号,和发送带数据TCP段一样设置为出站数据的当前序列号,且当前序列号是最终序列号FSN1,因为马上要关闭了。
确认序列号 被设为TCP对等端A期望对方发送的下一个字节。对应TCP对等端B当前序列号CSN2。
设置ACK标志
设置FIN标志,指示此逻辑管道上没有其他数据需要发送。
ftp服务器关闭FTP会话的Fin-ack段
段2:来自TCP对等端B的ACK
与SYN类似,FIN包也会占用一个字节的序列空间,并且必须把它当作是一个字节数据来确认。所以B接收到FIN-ACK后必须发送一个ACK,具有如下特点:
序列号 设为出站数据的当前序列号CSN2
确认号字段被设为比对端A发送的最终序列号多1的值FSN1+1.
设置ACK标志。
ftp服务器关闭FTP会话的Fin-ack段的ACK
一旦FIN-ACK被确认,发送初始FIN-ACK端A就不能再发送数据了,这仅终止了一个逻辑管道的连接,TCP对等端B发送数据到A的逻辑管道仍然开放,B仍然可以发数据给A。
段三:来自TCP对等端B的FIN-ACK
前面对等端A向B发送数据的逻辑管道被关闭后,如果B向A发送数据的逻辑管道仍然有数据发送,且被对等端A确认,这就是TCP半关闭。TCP对等端B向A发送数据的逻辑管道没有数据发送后,也要B向A发送FIN-ACK来关闭。
特点:
序列号,和发送带数据TCP段一样设置为出站数据的当前序列号,且当前序列号最终序列号FSN2,因为马上要关闭了。
确认序列号 被设为TCP对等端A期望对方发送的下一个字节。对应TCP对等端A当前序列号FSN1+1。
设置ACK标志
设置FIN标志,指示此逻辑管道上没有其他数据需要发送
ftp客户端关闭FTP会话的Fin-ack段
段四:来自TCP对等端A的ACK
同样段三的FIN-ACK包也按占用了一个字节算,并且必须作为一个字节的数据被确认。因此收到FIN-ACK的A必须发送一个ACK。
具有如下特点:
序列号 设为出站数据的当前序列号FSN1+1
确认号字段被设为比对端B发送的最终序列号多1的值FSN2+1
设置ACK标志。
ftp客户端关闭FTP会话的Fin-ack段的ACk
当来自A的ACK被B接收后,TCP连接上的B向A发送数据的逻辑管道就会被关闭,此时经过四次握手后,整个TCP连接才会被完整关闭。
但在有些实现中段二和段段三被合并。其过程就是FIN-ACK/FIN-ACK/ACK,此时中间的FIN-ACK中的ACK是对第一个FIN-ACK的确认。
同时关闭
双方都执行主动关闭也是可能的,TCP协议也允许这样的同时关闭(simultaneous close)。双方各发送一个FIN,两个FIN经过网络传送后分别到达另一端。收到FIN后,两端发送最后的ACK。当收到最后的A C K时,关闭TCP连接.
同时关闭的报文段交换
TCP连接的复位(Reset)
TCP连接终止进程适用于一个TCP连接的两个管道在互相同意的情况下正常关闭。另外一种终止TCP连接的方式是通过TCP连接复位—一个具有RST(Reset)标志的TCP段来完成。
当一个不可调和的入站TCP段的TCP头中存在参数问题时,一个TCP连接复位就会被发送。例如,不恰当的源IP地址、目的IP地址或者TCP端口号都能中断一个建立了的连接。中断的TCP连接将丢失所有的TCP数据,包括正在传送中或者在等待被发送的缓冲区中。
TCP也用来拒绝一个TCP连接企图,以响应对SYN段的接收。最常见的是,SYN段中目的端口与运行在SYN段接收者上的应用层进程相对应。当达到被允许的最大值时,连接企图就会被拒绝。下图显示了TCP连接复位
一个显示SYN和RST段的TCP连接的复位
注意:当UDP到达一个与应用层进程不对应的目的端口时,会产生一个ICMP,目的不可达-端口不可达的报错发送给UDP数据发送方。
抓包截图显示了在一台运行FTP客户端和一台非FTP服务器主机之间的包交换。帧一是一个到FTP控制端口的SYN段,帧二是连接复位。
在连接复位段中:
1.设置了RST和ACK标志
2.序列号为0
3.确认号比SYN段的序列号多1
4.窗口大小是0.
三 TCP连接状态
TCP连接状态和说明:
状态 说明
CLOSED 不存在TCP连接
LISTEN 一个应用层协议已经发布了一个被动打开,并且有意接收TCP连接企图
SYN SENT 一个应用层协议已经发布一个主动打开,并且发送一个SYN段
SYN RCVD 一个SYN段被接收,并且一个SYN-ACK被发送
ESTABLISHED 建立TCP连接的3此握手完成。现在数据能双向传输
FIN WAIT-1 初始的关闭连接段的FIN-ACK被发送
FIN WAIT-2 响应初始的FIN-ACK的ACK被接收
CLOSING 一个FIN-ACK被接收但ACK不是针对已发送的FIN-ACK的。收到的FIN-ACK中的是针对已发送的FINA-ACK被称为同时关闭,这时两个TCP对等端在相同时刻发送FIN-ACK。
TIME WAIT FIN- ACK已被发送并得到两个对等端的确认,并且TCP连接终止进程完成。一旦到达TIME WAIT状态,在连接的TCP端口能被重新使用前,TCP必须等待的时间是最大生存时间(MSL)的两倍。MSL是在互联网中一个TCP段能存在时间的最 大值,推荐是240秒。这个延迟防止一个使用相同端口的连接的TCP段与旧连接的TCP段的副本相混淆
CLOSE WAIT 一个FIN-ACK被接收,并且一个FIN-ACK被发送
LAST ACK 响应FIN-ACK的ACK已被接收
TCP状态变迁图
一个TCP对等端经过的连接状态依赖于TCP对等端是TCP连接建立的初始化方还是TCP连接终止的初始化方。
TCP连接图和终止图
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索服务器
, tcp
, 数据
, 进程
端口
tcp连接的建立与终止、tcp ip详解视频教程、tcp被360终止了、tcp ip详解 卷一、tcp ip详解,以便于您获取更多的相关知识。