动手学习TCP:数据传输(转)

本文涉及的产品
数据传输服务 DTS,数据同步 small 3个月
推荐场景:
数据库上云
数据传输服务 DTS,数据迁移 small 3个月
推荐场景:
MySQL数据库上云
数据传输服务 DTS,数据同步 1个月
简介: 前面的文章介绍了TCP状态变迁,以及TCP状态变迁图中的一些特殊状态。 本文主要看看TCP数据传输过程中需要了解的一些重要点: MSS(Maximum Segment Size) Seq号和Ack号的计算 TCP半连接 TCP数据传输实验 在开始介绍上面列出的内容之前,先看看实验程序的运行。

前面的文章介绍了TCP状态变迁,以及TCP状态变迁图中的一些特殊状态。

本文主要看看TCP数据传输过程中需要了解的一些重要点:

  • MSS(Maximum Segment Size)
  • Seq号和Ack号的计算
  • TCP半连接

TCP数据传输实验

在开始介绍上面列出的内容之前,先看看实验程序的运行。

本文的例子代码是基于"动手学习TCP:客户端状态变迁"文章中的例子。

首先,修改了"BuildTcpPacket"这个函数,增加了两个功能:

  1. 正常情况下TCP首部是20个字节,但是TCP首部支持一些特殊"Options"(MSS就是其中一个);所以,第一个改动就是支持创建带特殊选项的TCP包
  2. 第二个改动是可以通过参数设置为TCP包增加Payload,这样就可以通过TCP包传输数据了。
复制代码
public static Packet BuildTcpPacket(EndPointInfo endPointInfo, TcpControlBits tcpControlBits, List<TcpOption> tcpOptionList = null, bool withPayload = false, string payloadData = "") { EthernetLayer ethernetLayer = new EthernetLayer { Source = new MacAddress(endPointInfo.SourceMac), Destination = new MacAddress(endPointInfo.DestinationMac), EtherType = EthernetType.None, // Will be filled automatically.  }; IpV4Layer ipV4Layer = new IpV4Layer { Source = new IpV4Address(endPointInfo.SourceIp), CurrentDestination = new IpV4Address(endPointInfo.DestinationIp), Fragmentation = IpV4Fragmentation.None, HeaderChecksum = null, // Will be filled automatically. Identification = 123, Options = IpV4Options.None, Protocol = null, // Will be filled automatically. Ttl = 10, TypeOfService = 0, }; TcpLayer tcpLayer = new TcpLayer { SourcePort = endPointInfo.SourcePort, DestinationPort = endPointInfo.DestinationPort, Checksum = null, // Will be filled automatically. SequenceNumber = seqNum, AcknowledgmentNumber = ackNum, ControlBits = tcpControlBits, Window = windowSize, UrgentPointer = 0, Options = (tcpOptionList == null) ? TcpOptions.None : new TcpOptions(tcpOptionList), }; PacketBuilder builder; if (withPayload) { PayloadLayer payloadLayer = new PayloadLayer { Data = new Datagram(System.Text.Encoding.ASCII.GetBytes(payloadData)), }; builder = new PacketBuilder(ethernetLayer, ipV4Layer, tcpLayer, payloadLayer); return builder.Build(DateTime.Now); } builder = new PacketBuilder(ethernetLayer, ipV4Layer, tcpLayer); return builder.Build(DateTime.Now); }
复制代码

代码其余的改动发生在"PacketHandler"函数中:

private static void PacketHandler(PacketCommunicator communicator, EndPointInfo endPointInfo, bool clientToSendFin = true)

增加了对于"ESTABLISHED"状态下收到数据包的处理,主要作用就是发送一个[ACK]包对收到的数据包进行确认。

复制代码
case TcpControlBits.Acknowledgment:
    if (tcpStatus == TCPStatus.FIN_WAIT_1)
    {
        tcpStatus = TCPStatus.FIN_WAIT_2;
        Utils.PacketInfoPrinter(packet, tcpStatus);
    }
    else if (tcpStatus == TCPStatus.LAST_ACK) { tcpStatus = TCPStatus.CLOSED; Utils.PacketInfoPrinter(packet, tcpStatus); running = false; } else if (tcpStatus == TCPStatus.ESTABLISHED) { //print the data received from server  Console.WriteLine(packet.Ethernet.IpV4.Tcp.Payload.ToString()); communicator.SendPacket(Utils.BuildTcpResponsePacket(packet, TcpControlBits.Acknowledgment)); } break; case (TcpControlBits.Acknowledgment | TcpControlBits.Push): if (tcpStatus == TCPStatus.ESTABLISHED) { //print the data received from server  Console.WriteLine(packet.Ethernet.IpV4.Tcp.Payload.ToString()); communicator.SendPacket(Utils.BuildTcpResponsePacket(packet, TcpControlBits.Acknowledgment)); } break;
复制代码

运行效果

代码修改好之后,运行代码。

通过console端可以看到,在连接为"ESTABLISHED"状态下,客户端收到的来自服务端的字节数。

通过Wireshark抓包可以看到,在连接建立请求包[SYN]中增加了MSS的设置,并且以后的数据传出中,TCP数据包的payload长度最大就是MSS的值。

下面就开始介绍上面实验中涉及的TCP数据传输的知识点。

TCP分段和IP分片

在网络上传输的数据包是有大小限制,这里就需要知道TCP分段和IP分片的概念了。

跟这两个概念紧密相关的就是MSS(Maximum Segment Size)和MTU(Maximum Transmission Unit)这两个指标了,这两个指标的值大小直接决定了TCP分段和IP分片。

下面分别看看MSS和MTU。

MTU

首先来看看MTU。

以太网和802.3对数据帧的长度都有一个限制,最大值分别是1500和1492个字节。链路层的这个指标称作MTU(注意MTU是链路层的概念),不同类型的网络大多数都有一个上限。

如果网络层(IP层)有一个数据报需要传输,且数据的长度比链路层的 MTU还大,那么网络层(IP层)就要进行分片(fragmentation),把数据报分成若干片,保证每一个分片都小于MTU;目的端的网络层(IP层)会对收到的分片进行重新组装。

也就是说,分片和重新组装过程发生在网络层(IP层),所以对运输层(TCP/UDP)是透明的。

下面看看通过ping命令演示IP分片,ping命令属于ICMP(Internet Control Messages Protocol)协议:

Wireshark的结果为下,这5000个字节的数据被分别放在了四个IP分片中,每个分片(最后一个分片除外)中的数据长度等于1480(1500 – 20[IP header]):

IP分片的问题:IP分片有一个很大的问题,由于IP层本身没有超时重传机制,即使只丢失一片数据也要重新传整个数据报。也就是说,对于上面截图中的4个Frame,任何一个丢失了,另外3个都需要进行重传。

使用UDP和ICMP的时候很容易导致IP分片,因为UDP和ICMP是不考虑MTU和分片的,而是把这些工作都丢给了网络层(IP层);但是,为了减少IP分片对TCP的影响,在TCP中提出了MSS来试图避免IP分片

MSS

MSS就是TCP数据包每次能够传输的最大数据分段。

为了达到最佳的传输效能TCP协议在建立连接的时候通常要协商双方的MSS值,这个值TCP协议在实现的时候往往用MTU值代替(需要减去IP数据包首部的大小20Bytes和TCP数据段的首部20Bytes),所以往往MSS为1460。通讯双方会根据双方提供的MSS值得最小值确定为这次连接的最大MSS值。

回到本文开始的例子,在建立TCP连接的时候,客户端指定了MSS为800,服务端指定的MSS为1460。经过协商后,双方采用了较小的MSS,所以以后的数据包长度最到为800字节。TCP就是通过这种方式来避免IP分片的。

再看一个MSS的例子,通过Wireshark抓取了一段HTTP请求,通过GET方法请求jquery的一组数据包。

通过下面可以看到,当应用层有一个超过MSS的数据需要发送的时候,TCP会把应用层的数据分成多个TCP分段然后发送出去。每一个分段包都包含TCP首部,然后传递给网络层进一步增加IP首部。

区别

通过上面可以看到TCP分段和IP分片有下面的主要区别:

  1. TCP分段发生在传输层,分段的依据是MSS;IP分片发生在网络层,分片的依据是MTU
  2. TCP分段是在传输层完成,并在传输层进行重组;IP分片由网络层完成,也在网络层进行重组

再看Seq和Ack号

TCP传输的可靠性是通过Seq和Ack号来进行保证的,所以可以看出Seq和Ack号的重要性。

文章开始的实验中,另一个需要注意的地方就是Seq和Ack号的变化。

在前面TCP连接的相关文章中已经介绍了连接建立和终止时候Seq和Ack号的变化,可以总结得到下面公式:

确认包的Ack = 待确认包(特殊标志包)的Seq + 1

从Wireshark的截图中可以看到在数据传输中Seq和Ack号的变化。

对于数据包的确认,可以使用下面的方式进行计算:

确认包的Ack = 待确认数据包的Seq + 待确认数据包的数据长度(Len)

关于TCP半连接

在介绍TCP终止连接的时候,提到了由于TCP是全双工的,所以需要经过四次挥手才能关闭TCP连接。

TCP中有一个半连接的概念,就是TCP连接的一端在结束它的发送后,还能接收来自另一端数据。

还是回到文章开始的例子,服务端发出了终止TCP连接的请求[FIN, ACK],客户端进行了确认,到此服务端到客户端方向的TCP连接就关闭了。

但是,随后客户端向服务端发送了一段长度为480字节的数据,然后才关闭客户端到服务端方向的TCP连接。

总结

本文主要介绍了TCP数据传输中的几个重要的概念。

  • MSS(Maximum Segment Size)
  • Seq号和Ack号
  • TCP半连接

通过这篇文章,一定能很好的认识TCP分段和IP分片的区别,以及MSS和MTU的关系

http://www.cnblogs.com/wilber2013/p/4853674.html

 

相关实践学习
部署高可用架构
本场景主要介绍如何使用云服务器ECS、负载均衡SLB、云数据库RDS和数据传输服务产品来部署多可用区高可用架构。
Sqoop 企业级大数据迁移方案实战
Sqoop是一个用于在Hadoop和关系数据库服务器之间传输数据的工具。它用于从关系数据库(如MySQL,Oracle)导入数据到Hadoop HDFS,并从Hadoop文件系统导出到关系数据库。 本课程主要讲解了Sqoop的设计思想及原理、部署安装及配置、详细具体的使用方法技巧与实操案例、企业级任务管理等。结合日常工作实践,培养解决实际问题的能力。本课程由黑马程序员提供。
相关文章
|
8月前
|
网络协议 算法 安全
TCP/UDP 数据传输的链路解析
TCP/UDP 数据传输的链路解析
137 0
|
5月前
|
网络协议 安全 算法
"网络世界的守护者:一探究竟TCP协议如何确保数据传输的绝对安全与可靠"
【8月更文挑战第20天】传输控制协议(TCP)是网络通信中的核心协议之一,它确保数据包能可靠、有序地从源头传输到目的地。TCP采用三次握手的方式建立连接,并通过序列号、确认应答及超时重传来保障数据传输的准确性。此外,TCP还具备流量控制与拥塞控制功能,避免网络拥塞。虽然TCP在可靠性上表现优异,但在快速传输场景中可能存在局限。深入理解TCP对于网络工程师和开发者至关重要。
98 1
|
5月前
|
网络协议 安全
揭秘TCP背后的秘密:为何三次握手是连接的灵魂,四次挥手是告别的艺术,让数据传输稳如老狗!
【8月更文挑战第4天】TCP为何需三次握手和四次挥手?三次握手确保连接建立时双方均准备好并确认序列号,过程包括:客户端发SYN包;服务器回应SYN+ACK;客户端再回ACK确认,确保可靠通信。四次挥手则确保连接终止时双方能安全、有序地结束数据传输,包括客户端发FIN包;服务器回应ACK并可能继续发送数据;完成后发FIN包;客户端最终确认,确保无数据丢失或状态不一致。
97 9
|
6月前
|
网络协议 程序员 定位技术
学习网络的第一步:全面解析OSI与TCP/IP模型
**网络基础知识概览:** 探索网络通信的关键模型——OSI七层模型和TCP/IP五层模型。OSI模型(物理、数据链路、网络、传输、会话、表示、应用层)提供理论框架,而TCP/IP模型(物理、数据链路、网络、传输、应用层)更为实际,合并了会话、表示和应用层。两者帮助理解数据在网络中的传输过程,为网络设计和管理提供理论支持。了解这些模型,如同在复杂的网络世界中持有了地图。
115 2
|
7月前
|
网络协议 API 开发者
无线通信模块通过TCP/IP协议实现与PC端的数据传输
本文介绍了无线通信模块借助TCP/IP协议向PC端传输数据的过程,包括数据封装、发送和接收,并以WIFI模块为例,讨论了在QT平台下实现无线数据传输的方法。通过QTcpSocket类,开发者能轻松建立WIFI模块与PC间的连接。随着无线通信技术的进步,未来将有更多创新应用出现。
|
7月前
|
存储 网络协议 网络安全
逆向学习网络篇:数据传输和交换过程
逆向学习网络篇:数据传输和交换过程
61 0
|
网络协议 安全 Linux
解密TCP连接断开:四次挥手的奥秘和数据传输的安全
本文将介绍TCP连接的断开过程,重点关注四次挥手的过程和状态变迁,以及为什么挥手需要四次和为什么需要TIME_WAIT状态。在TCP连接断开的过程中,双方需要发送FIN和ACK报文来确保数据的可靠传输和连接的正确关闭。挥手需要四次的原因是为了确保数据的完整传输和连接的可靠关闭。
808 1
解密TCP连接断开:四次挥手的奥秘和数据传输的安全
|
机器学习/深度学习 监控 网络协议
浅谈 TCP 握手/数据传输/挥手过程以及 tcpdump 抓包工具使用
浅谈 TCP 握手/数据传输/挥手过程以及 tcpdump 抓包工具使用
337 0
|
缓存 开发工具 数据安全/隐私保护
【软考学习17】数据传输控制方式、虚设备和微内核操作系统
【软考学习17】数据传输控制方式、虚设备和微内核操作系统
184 0
|
存储 缓存 网络协议
网络基础学习:什么是tcp/ip协议
网络基础学习:什么是tcp/ip协议
174 0

热门文章

最新文章