分析TCP/IP协议栈代码之TCP
2016-07-05 18:30
309 查看
1. TCP介绍
TCP与UDP都属于传输层,但是与UDP不同的是,TCP是面向连接的,可靠的传输协议。
ps:需要找几篇文章来看看两者的不同和各自的用武之地了,虽然对下面的代码分析之后对何为“面向连接”,何为“可靠”有一个具象的了解,但是不够全面和系统,比如何时采用TCP,何时采用UDP,效果如何,当然还得解释清楚其中的原因所在。
2. TCP首部
TCP数据被封装在一个IP数据报中,如图17 - 1所示。
图17 - 2显示TCP首部的数据格式。如果不计任选字段,它通常是20个字节。
每个TCP段都包含源端和目的端的端口号,用于寻找发端和收端应用进程。这两个值加上IP首部中的源端IP地址和目的端IP地址唯一确定一个TCP连接。有时,一个IP地址和一个端口号也称为一个插口或套接字(socket) 。这个术语出现在最早的TCP规范(RFC793)中,后来它也作为表示伯克利版的编程接口 。插口对或套接字对(socket pair)(包含客户IP地址、客户端口号、服务器 IP地址和服务器端口号的四元组 )可唯一确定互联网络中每个TCP连接的双方。
序号用来标识从TCP发端向TCP收端发送的数据字节流,它表示在这个报文段中的的第一个数据字节。如果将字节流看作在两个应用程序间的单向流动,则 TCP用序号对每个字节进行计数。序号是32 bit的无符号数,序号到达2^32-1后又从0开始。
在TCP首部中有6个标志比特(此处结合下面的状态变迁图是实现的关键之所在)。它们中的多个可同时被设置为 1。我们在这儿简单介绍它们的用法,在随后的章节中有更详细的介绍。
URG 紧急指针(urgent pointer)有效(见2 0 . 8节) 。
ACK 确认序号有效。
PSH 接收方应该尽快将这个报文段交给应用层。
RST 重建连接。
SYN 同步序号用来发起一个连接。这个标志和下一个标志将在第 18章介绍。
FIN 发端完成发送任务。
TCP的流量控制由连接的每一端通过声明的窗口大小来提供。窗口大小为字节数,起始于确认序号字段指明的值,这个值是接收端正期望接收的字节。窗口大小是一个 16bit字段,因而窗口大小最大为65535字节。在24 . 4节我们将看到新的窗口刻度选项,它允许这个值按比例变化以提供更大的窗口。
检验和覆盖了整个的TCP报文段:TCP首部和TCP数据。这是一个强制性的字段,一定是由发端计算和存储,并由收端进行验证。 TCP检验和的计算和UDP检验和的计算相似,使用如11 . 3节所述的一个伪首部。
只有当URG标志置1时紧急指针才有效。紧急指针是一个正的偏移量,和序号字段中的值相加表示紧急数据最后一个字节的序号。 TCP的紧急方式是发送端向另一端发送紧急数据的一种方式。我们将在20 . 8节介绍它。
最常见的可选字段是最长报文大小,又称为 MSS (Maximum Segment Size)。每个连接方通常都在通信的第一个报文段(为建立连接而设置 SYN标志的那个段)中指明这个选项。它指明本端所能接收的最大长度的报文段。我们将在 18 . 4节更详细地介绍MSS选项,TCP的其他选项中的一些将在第24章中介绍。从图17 - 2中我们注意到TCP报文段中的数据部分是可选的。我们将在 18章中看到在一个连接建立和一个连接终止时,双方交换的报文段仅有
TCP首部。如果一方没有数据要发送,也使用没有任何数据的首部来确认收到的数据。在处理超时的许多情况中,也会发送不带任何数据的报文段。
小结:
TCP提供了一种可靠的面向连接的字节流运输层服务。我们简单地介绍了 TCP首部中的各个字段,并在随后的几章里详细讨论它们。
TCP将用户数据打包构成报文段;它发送数据后启动一个定时器;另一端对收到的数据进行确认,对失序的数据重新排序,丢弃重复数据; TCP提供端到端的流量控制,并计算和验证一个强制性的端到端检验和。
许多流行的应用程序如Telnet、Rlogin、FTP和SMTP都使用TCP。
3. TCP连接的建立与终止
3.1 建立连接协议
请求端(通常称为客户)发送一个 SYN段指明客户打算连接的服务器的端口,以及初
始序号(ISN,在这个例子中为1415531521) 。这个SYN段为报文段1。
服务器发回包含服务器的初始序号的SYN报文段(报文段2)作为应答。同时,将确认
序号设置为客户的ISN加1以对客户的SYN报文段进行确认。一个SYN将占用一个序号。
客户必须将确认序号设置为服务器的 ISN加1以对服务器的SYN报文段进行确认(报文
段3) 。
这三个报文段完成连接的建立。这个过程也称为三次握手( three-way handshake) 。
以下为WireShark的建立连接数据的抓包,其中HTTP为服务器端:
注意:这里PC端的默认MSS是1460(因为是以太网),而STM32端的MSS是1408,这个可以在程序里面修改。
3.2 连接终止协议
建立一个连接需要三次握手,而终止一个连接要经过 4次握手。如下图所示,过程与建立连接的三次握手过程类似。
4. TCP的状态变迁图
ps:跟着箭头走就ok了,当然不会所有的状态变迁都实现,看具体协议栈的实现,下面的代码就只实现了其中的一部分。
ESTABLISHED状态是连接双方能够进行双向数据传递的状态。
注意:并不是所有的状态变迁都需要实现的,这取决于协议栈的具体实现,但是必须要有至少一条状态回路来保证数据的传输。
TCP与UDP都属于传输层,但是与UDP不同的是,TCP是面向连接的,可靠的传输协议。
ps:需要找几篇文章来看看两者的不同和各自的用武之地了,虽然对下面的代码分析之后对何为“面向连接”,何为“可靠”有一个具象的了解,但是不够全面和系统,比如何时采用TCP,何时采用UDP,效果如何,当然还得解释清楚其中的原因所在。
2. TCP首部
TCP数据被封装在一个IP数据报中,如图17 - 1所示。
图17 - 2显示TCP首部的数据格式。如果不计任选字段,它通常是20个字节。
每个TCP段都包含源端和目的端的端口号,用于寻找发端和收端应用进程。这两个值加上IP首部中的源端IP地址和目的端IP地址唯一确定一个TCP连接。有时,一个IP地址和一个端口号也称为一个插口或套接字(socket) 。这个术语出现在最早的TCP规范(RFC793)中,后来它也作为表示伯克利版的编程接口 。插口对或套接字对(socket pair)(包含客户IP地址、客户端口号、服务器 IP地址和服务器端口号的四元组 )可唯一确定互联网络中每个TCP连接的双方。
序号用来标识从TCP发端向TCP收端发送的数据字节流,它表示在这个报文段中的的第一个数据字节。如果将字节流看作在两个应用程序间的单向流动,则 TCP用序号对每个字节进行计数。序号是32 bit的无符号数,序号到达2^32-1后又从0开始。
在TCP首部中有6个标志比特(此处结合下面的状态变迁图是实现的关键之所在)。它们中的多个可同时被设置为 1。我们在这儿简单介绍它们的用法,在随后的章节中有更详细的介绍。
URG 紧急指针(urgent pointer)有效(见2 0 . 8节) 。
ACK 确认序号有效。
PSH 接收方应该尽快将这个报文段交给应用层。
RST 重建连接。
SYN 同步序号用来发起一个连接。这个标志和下一个标志将在第 18章介绍。
FIN 发端完成发送任务。
TCP的流量控制由连接的每一端通过声明的窗口大小来提供。窗口大小为字节数,起始于确认序号字段指明的值,这个值是接收端正期望接收的字节。窗口大小是一个 16bit字段,因而窗口大小最大为65535字节。在24 . 4节我们将看到新的窗口刻度选项,它允许这个值按比例变化以提供更大的窗口。
检验和覆盖了整个的TCP报文段:TCP首部和TCP数据。这是一个强制性的字段,一定是由发端计算和存储,并由收端进行验证。 TCP检验和的计算和UDP检验和的计算相似,使用如11 . 3节所述的一个伪首部。
只有当URG标志置1时紧急指针才有效。紧急指针是一个正的偏移量,和序号字段中的值相加表示紧急数据最后一个字节的序号。 TCP的紧急方式是发送端向另一端发送紧急数据的一种方式。我们将在20 . 8节介绍它。
最常见的可选字段是最长报文大小,又称为 MSS (Maximum Segment Size)。每个连接方通常都在通信的第一个报文段(为建立连接而设置 SYN标志的那个段)中指明这个选项。它指明本端所能接收的最大长度的报文段。我们将在 18 . 4节更详细地介绍MSS选项,TCP的其他选项中的一些将在第24章中介绍。从图17 - 2中我们注意到TCP报文段中的数据部分是可选的。我们将在 18章中看到在一个连接建立和一个连接终止时,双方交换的报文段仅有
TCP首部。如果一方没有数据要发送,也使用没有任何数据的首部来确认收到的数据。在处理超时的许多情况中,也会发送不带任何数据的报文段。
小结:
TCP提供了一种可靠的面向连接的字节流运输层服务。我们简单地介绍了 TCP首部中的各个字段,并在随后的几章里详细讨论它们。
TCP将用户数据打包构成报文段;它发送数据后启动一个定时器;另一端对收到的数据进行确认,对失序的数据重新排序,丢弃重复数据; TCP提供端到端的流量控制,并计算和验证一个强制性的端到端检验和。
许多流行的应用程序如Telnet、Rlogin、FTP和SMTP都使用TCP。
3. TCP连接的建立与终止
3.1 建立连接协议
请求端(通常称为客户)发送一个 SYN段指明客户打算连接的服务器的端口,以及初
始序号(ISN,在这个例子中为1415531521) 。这个SYN段为报文段1。
服务器发回包含服务器的初始序号的SYN报文段(报文段2)作为应答。同时,将确认
序号设置为客户的ISN加1以对客户的SYN报文段进行确认。一个SYN将占用一个序号。
客户必须将确认序号设置为服务器的 ISN加1以对服务器的SYN报文段进行确认(报文
段3) 。
这三个报文段完成连接的建立。这个过程也称为三次握手( three-way handshake) 。
以下为WireShark的建立连接数据的抓包,其中HTTP为服务器端:
注意:这里PC端的默认MSS是1460(因为是以太网),而STM32端的MSS是1408,这个可以在程序里面修改。
3.2 连接终止协议
建立一个连接需要三次握手,而终止一个连接要经过 4次握手。如下图所示,过程与建立连接的三次握手过程类似。
4. TCP的状态变迁图
ps:跟着箭头走就ok了,当然不会所有的状态变迁都实现,看具体协议栈的实现,下面的代码就只实现了其中的一部分。
ESTABLISHED状态是连接双方能够进行双向数据传递的状态。
注意:并不是所有的状态变迁都需要实现的,这取决于协议栈的具体实现,但是必须要有至少一条状态回路来保证数据的传输。
相关文章推荐
- TCP版backshell的VBS脚本代码
- 使用C语言编写基于TCP协议的Socket通讯程序实例分享
- TCP Wrappers防火墙介绍与封锁IP地址的方法
- c语言多进程tcp服务器示例
- win2003连接限制TCP连接限制
- PowerShell脚本开发之收发TCP消息包
- Nodejs创建TCP服务器 - king0222
- C#实现TCP连接信息统计的方法
- linux shell 脚本实现tcp/upd协议通讯(重定向应用)
- 使用C#实现基于TCP和UDP协议的网络通信程序的基本示例
- Android使用socket创建简单TCP连接的方法
- Android实现TCP客户端接收数据的方法
- Android TCP 文件客户端与服务器DEMO介绍
- Android中实现TCP和UDP传输实例
- python实现可将字符转换成大写的tcp服务器实例
- php实现TCP端口检测的方法
- Java Socket编程实例(一)- TCP基本使用
- Java Socket编程实例(三)- TCP服务端线程池
- Java实现Socket的TCP传输实例
- 实现了基于TCP的Java Socket编程实例代码