我不是计算机科班出身。记得大学的时候旁听计算机系的网络课,当时计算机系使用教材是"计算机网络--自顶向下方法与Internet特色"的影印版,这本教材与众不同的一个地方就是作者JAMES F.KUROSE和KEITH W.ROSS采用了'自顶向下'的编排思路,先从应用层开始,最后讲到物理层。而且这本书在语言上形象生动,通俗易懂。只怪我当初没有一心一意听讲,到现在存在我的脑子中的基本概念居多,深刻理解甚少。以致于工作后遇到此类的问题,只能恶补。这不,在12月1日凌晨全国统一短信类服务接入代码的调整工作中,我就遇到了此类问题,不得不再次抱起W.Richard Stevens的'TCP详解卷一'啃了啃,回顾一下TCP协议那些事儿。
做应用层网络程序开发的,手头上都有一把利器:抓包工具,更专业的名词就是协议分析工具,常用的且功能强大的协议分析工具有:TCPDUMP(Windows平台上的叫Windump)、Ethereal等。工作中常常会遇到因应用层程序在协议字段发送和接收解析上不一致而出现'纠纷'问题,这时我们一般采用的在TCP层用协议分析工具抓取该层原始数据包作为'对峙'的证据;还有的就是在客户端与服务器端链接问题上的一些现象也需要到TCP层去分析原因,这就需要对TCP层的基本工作原理有一个清晰的认识。
首先我们要明确:TCP头部中设置的一系列域都是为了能达到分割、重传、查重、重组、流控、全双工的协议功能而设置的,这里比较重要的字段就是序列号和确认号。由于要达到重传、查重、重组、全双工这些目的,TCP层需要通过序列号和确认号来保证。序列号用来标识发送端传送数据包的顺序,并且指导接收端对多数据包进行顺序重组;发送端传送一个数据包后,它会把这个数据包放入重发队列中,同时启动计时器,如果收到了关于这个包的确认信息,便将此数据包从队列中删除;如果在计时器超时的时候仍然没有收到确认信息,则需要重新发送该数据包。
TCP层以"三次握手"建立链接而"闻名于世",三次握手的目的:建立链接,为后续的数据流传输奠基,因为TCP是双工的,因此在握手过程需告知彼此数据包发送的起始序列号。
Client --> 置SYN标志 序列号 = J,确认号 = 0 ----> Server
Client <-- 置SYN标志 置ACK标志 序列号 = K, 确认号 = J + 1 <-- Server
Clinet --> 置ACK标志 序列号 = J + 1,确认号 = K + 1 --> Server
链接建立后,接下来Client端发送的数据包将从J + 1开始,Server端发送的数据包将从K + 1开始,这里要说明的是:建立链接时,Client端宣称自己的初始序列号是J,Server端宣称自己的初始序列号是K,但是建立连接后的数据包却各自中初始序列号+1开始,这是因为SYN请求本身需要占用一个序列号。
在数据传输阶段,按照常理应用层数据的传输是这样的:(我们假定建立连接阶段Client端最后的确认包中序列号 = 55555, 确认号 = 22222)
Client --> 置PSH标志,置ACK标志 序列号 = 55555, 确认号 = 22222,数据包长度 = 11 ---> Server
Client <-- 置ACK标志,序列号 = 22222, 确认号 = 55566 (=55555 + 11),数据包长度 = 0 <--- Server
Client <-- 置PSH标志,置ACK标志 序列号 = 22223, 确认号 = 55566,数据包长度 = 22 <--- Server
Client --> 置ACK标志,序列号 = 55566, 确认号 = 22244(=22222+22),数据包长度 = 0 ---> Server
注:PSH标志指示接收端应尽快将数据提交给应用层。从我协议分析的经历来看,在数据传输阶段,几乎所有数据包的发送都置了PSH位;而ACK标志位在数据传输阶段也是一直是置位的。
但是实际我们在分析过程看到的却都是如下这样的:
Client --> 置PSH标志,置ACK标志 序列号 = 55555, 确认号 = 22222,数据包长度 = 11 ---> Server
Client <-- 置PSH标志,置ACK标志 序列号 = 22222, 确认号 = 55566 (=55555 + 11),数据包长度 = 22 <--- Server
Client --> 置PSH标志,置ACK标志 序列号 = 55566, 确认号 = 22244 (=22222 + 22),数据包长度 = 33 ---> Server
Client <-- 置PSH标志,置ACK标志 序列号 = 22244, 确认号 = 55599 (=55566 + 33),数据包长度 = 44 <--- Server
也就是说:数据接收端将上一个应答和自己待发送的应用层数据组合在一起发送了。TCP的传输原则是尽量减少小分组传输的数量,所以一般默认都开启"带时延的ACK"。一般实现中,时延在200ms。Nagle算法多用来实现"带时延的ACK",它要求一个TCP连接上最多只能有一个未被确认的小分组。在该分组的确认到达之前不能发送其他小分组。也就是说:发送端在发送一个分组后,需等待这个分组的ACK确认后,才可以进行下一个分组的发送。这样一来网络的传输效率被大大降低了。对于大数据块的传输来说,这样很多时候是难以忍受的。另一种拥塞控制策略被引入,那就是TCP的滑动窗口协议,滑动窗口协议是分组发送和分组确认不再同步,发送端可以连续发送n个分组,接收端同样也可以用一个确认包来一起确认这n个分组,通常n = 2。各种OS的TCP协议栈在实现上都是综合了Nagle算法和滑动窗口协议的,TCP层对应用层数据分组大小进行多次判断(一般分组大小都是和MSS做比较的),以在Nagle和滑动窗口协议之间抉择到底选择哪一种控制方式进行发送。"The Linux Network Architecture: Design and Implementation of Network Protocols in the Linux Kernel"一书介绍了Linux在TCP层上的设计和实现,当然最直观的还是去分析Linux源代码了。
拆除TCP连接过程用一句话表述就是:你关你的发送通道,我关我的发送通道(因为TCP是全双工)。当一方关闭发送通道后,仍可接收另一方发送过来数据,这样的情况就成为"半关闭"。然而多数情况下,"半关闭"使用的很少,而且半关闭需要SOCKET AIP支持在SOCKET上的shutdown(而不是调用close)。
正常的关闭流程是源于Fin报文的:
Client --> Fin ACK --> Server
Client <-- ACK <-- Server
Client <-- Fin ACK -- Server
Client --> ACK --> Server
发送Fin分组的一端会先将发送缓冲中的报文按序发完之后,再发出Fin;所以说Fin又叫做:orderly release。
异常的关闭流程是源于Rst报文的。一个典型的例子就是当客户端所要链接的服务器端的端口并没有程序在listen,这时服务器端的TCP层会直接发送一个Rst报文,告诉客户端重置连接。Rst报文是无需确认的。客户端在收到Rst后会通知应用层对方异常结束链接(需通过SOCKET API的设置才能得知对方是异常关闭)。
分享到:
相关推荐
IP和相关协议 第9章 IP协议家族 77 9.1 TCP/IP模型 77 9.1.1 解剖TCP/IP模型 78 9.1.2 协议组件 78 9.2 理解网际协议(IP) 79 9.2.1 IPv4结构 79 9.2.2 IP做什么 80 9.3 理解传输控制协议...
标题中的"TCP.rar_28335 IP TCP_tcp 通信"可能是指一个关于TCP/IP通信的资源包,其中包含了一些与TCP相关的代码或文档,文件编号可能是"28335"。描述中提到"已经验证过了,可以编译通过",这表明这是一个实际操作过...
MODBUS-TCP是一种广泛应用于工业自动化领域的通信协议,它基于标准的TCP/IP协议栈,将MODBUS协议与网络层的TCP(传输控制协议)相结合,实现了设备间的远程通信。MODBUS-TCP允许不同制造商的设备在以太网或任何其他...
TCP调试助手源码是一款专为IT专业人士设计的工具,它帮助开发者深入了解TCP协议的工作机制,同时也为TCP编程提供了一个实践平台。源代码的开放性使得用户可以深入学习TCP协议的实现细节,理解网络通信的基本原理,并...
在Android平台上进行网络通信时,TCP(Transmission Control Protocol)是一种常用的方式,因为它提供了一种可靠的、面向连接的数据传输服务。本示例中的"android TCP server 和TCP client通信源码"着重于实现...
在IT领域,网络通信是计算机系统之间交换信息的基础,而TCP(Transmission Control Protocol)作为传输层协议,是网络通信的核心部分。本篇文章将详细探讨TCP服务端和TCP客户端的概念、工作原理以及常用的工具软件。...
本项目名为"tcp_TCP/IP_tcp_vb.net_VB.NET.tcp_",显然,它是一个使用VB.NET语言实现的TCP/IP通信示例。 TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。它的主要...
TCP转发工具是一种网络工具,主要用于将TCP连接从一个端点重定向到另一个端点,它在许多场景下都非常有用,比如穿透内网限制、代理服务、数据加密等。本项目提供的是一套用Java语言编写的TCP请求中转解决方案,旨在...
在IT行业中,网络通信是至关重要的一个领域,TCP(传输控制协议)和MODBUS-TCP则是其中两个常见的通信协议。TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议,而MODBUS-TCP是在TCP/IP协议栈上构建的一种...
TCP/IP协议是互联网通信的基础,它定义了网络设备如何交换数据和定位网络资源。TCP(传输控制协议)和IP(互联网协议)是该协议族的两个核心组件,负责端到端的数据传输。UDP(用户数据报协议)则是另一种常用协议,...
《TCP2ComV1:串口到TCP的通信桥梁》 在现代的计算机通信领域,TCP(Transmission Control Protocol)和串口(Serial Port)是两种常见的通信方式。TCP以其高可靠性、面向连接的特性,广泛应用于互联网通信;而串口...
**TCP端口监听工具——tcptrace** 在IT行业中,网络通信是不可或缺的一部分,而TCP(传输控制协议)作为互联网协议栈中的重要一环,其工作状态直接影响到应用层服务的稳定性和效率。tcptrace是一款强大的TCP端口...
TCP(Transmission Control Protocol)与UDP(User Datagram Protocol)是互联网协议中的两种主要传输层协议,它们在计算机网络通信中扮演着至关重要的角色。本测试工具专注于帮助开发者在创建网络通信程序时,对TCP...
一个串口转TCP的程序,能很好的满足远程串口传输、调试需求,功能如下: 1.支持打开物理串口和虚拟串口(不创建虚拟串口,但能打开其他工具创建的虚拟串口)。 2.支持通过TCP客户端连接到远程TCP服务器。 3.支持TCP...
Modbus TCP和TCP通信是工业自动化领域中广泛使用的通信协议,尤其在PLC(可编程逻辑控制器)之间进行数据交换时。本主题将深入探讨这两种通信方式及其在测试中的应用,特别是针对西门子SMART S7-200 PLC。 首先,让...
标题中的"VB(TCP-IP).rar_TCP服务器_VB TCP IP VB TCP/IP_tcp_vb客户服务器"表明这是一个关于使用Visual Basic(VB)进行TCP/IP通信的教程,特别关注TCP服务器的实现以及VB客户端和服务器之间的交互。这个压缩包可能...
标题中的“uip+tcp_client+tcp_server”指的是一个基于uIP协议栈的TCP客户端和服务器端程序。uIP是一个轻量级的TCP/IP协议栈,适用于资源有限的嵌入式设备,比如微控制器驱动的物联网设备。在这个项目中,我们有两个...
标题中的“Modbus TCP_modbustcpplc_ab1756modbustcp_modbusTCP_ab_PLCMODBUS_源”关键词表明了这个压缩包是关于使用Modbus TCP协议与Allen Bradley(AB)PLC进行通信的资源集合。描述中提到的“AB PLC MODBUS TCP ...
1. **TCP通信基础**:LabVIEW提供了丰富的TCP/IP函数库,如`TCP Open.vi`用于建立连接,`TCP Write.vi`用于发送数据,`TCP Read.vi`用于接收数据,以及`TCP Close.vi`用于关闭连接。理解这些函数的工作原理是进行TCP...
本示例主要探讨的是如何利用三菱Q内置的以太网模块进行MODBUS TCP通信,这是一种广泛应用的工业通讯协议,它允许不同设备之间通过以太网交换数据。以下是对这些知识点的详细说明: 首先,我们需要理解MODBUS协议。...