添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

本文对网上关于TCP/IP/UDP相关内容进行收集整理,引用部分参考文献内容作为章节补充,以对相关概念作较为清晰、且完整的表述。

本文对TCP/IP理论基础进行整理,同时提供一个 简单的 基于FPGA实现的TCP架构、相关状态转移图。该方案仅是一种初步设想,并非完整方案,时钟复位系统也需要独立设计,仅提供初步的设计构思基础、作为参考。

1、概念梳理(以太网帧/TCP协议/IP协议/UDP协议)

IP首部校验和 :占16位,只检验数据报的首部、不检验数据部分( 仅对IP首部20字节进行校验 )。采用二进制反码求和,即将16位数据相加后,再将进位与低16位相加,直到进位为0,最后将16位取反。

TCP首部校验和 :占16位,TCP校验和是一个端到端的校验和,由发送端计算,然后由接收端验证。其目的是为了发现TCP首部和数据在发送端到接收端之间发生的任何改动。如果接收方检测到校验和有差错,则TCP段会被直接丢弃。

TCP校验和 :覆盖 TCP伪首部 和TCP数据,而IP首部中的校验和只覆盖IP的首部,不覆盖IP数据报中的任何数据。TCP的校验和是必需的,而UDP的校验和是可选的。TCP和UDP计算校验和时,都要加上一个12字节的伪首部。

TCP伪首部: TCP校验和、IP校验和的计算方法是基本一致的,除了计算的范围不同.

首先,把伪首部、TCP报头、TCP数据分为16位的字,如果总长度为奇数个字节,则在最后增添一个位都为0的字节。

把TCP报头中的校验和字段置为0(否则就陷入鸡生蛋还是蛋生鸡的问题)。

其次,用反码相加法累加所有的16位字(进位也要累加)。

最后,对计算结果取反,作为TCP的校验和。

UDP伪首部:

UDP的校验和:包含 伪首部+数据 一起都检验。

UDP检验和的计算方法是:

  1. 按每16位求和得出一个32位的数;
  2. 如果这个32位的数,高16位不为0,则高16位加低16位再得到一个32位的数;
  3. 重复第2步直到高16位为0,将低16位取反,得到校验和。

源端口/目的端口

是0-65535任何数字,在收到请求时系统会为客户端动态分配,0-1023为知名端口号.
报文序号 用来标识从TCP源端向TCP目标端发送的数据字节流,它表示在这个报文段中的数据编号,用sequence表示.
确认序号 只有ACK标志为1时,确认号字段才有效,它包含目标端所期望收到源端的下一个数据编号,用acknowledge表示.
报文长度 因为选项长度不确定,取值范围是5-15(20-60byte).
URG 紧急标志位,紧急指针有效,1表示有效.
ACK 确认序号有效,1表示有效.
PSH 推送标志位,1表示接收方应该尽快将这个报文段交给应用层,但只是整个数据的一部分并不是所有,类似收到短信提醒一样.
RST

1表示重新连接.

SYN 1表示发起一个新的连接.
FIN 1表示释放一个连接,finish.
窗口尺寸(单位byte) 此字段用来进行流量控制,这个值是本机期望下一次接收的最大长度,带伪头部的TCP报头校验和:这个是伪头部(12+20+选项长度+数据长度)16位校验值.
紧急指针 它是一个偏移量(也就是先发的包长度),和报文序号字段中的值相加表示紧急数据最后一个字节的序号选项:可能包括"窗口扩大因子"、"时间戳"等选项.
CRC 从MAC到数据所有内容进行的CRC32校验结果,不论是传输层、网络层计算包长度时都不包含crc32这4个字节的长度,这是物理链路封包校验用的.

1.2 TCP 首部各字段的意义和作用

(本节引用自参考文献3)

源端口和目的端口 Port

各占 2 个 字节,共 4 个字节。
用来告知主机该报文段是来自哪里以及传送给哪个应用程序(应用程序绑定了端口)的。
进行 TCP 通讯时,客户端通常使用系统自动选择的临时端口号,而服务器则使用知名服务端口号。

序号 Sequence Number

占 4 个字节。
TCP 是面向字节流的,在一个 TCP 连接中传输的字节流中的每个字节都按照顺序编号。
例如 100 kb 的 HTML 文档数据,一共 102400 (100 * 1024) 个字节,那么每一个字节就都有了编号,整个文档的编号的范围是 0 ~ 102399。

序号字段值指的是 本报文段 所发送的数据的第一个字节的序号。
那么 100 的 HTML 文档分割成四个等分之后,
第一个 TCP 报文段包含的是第一个 25kb 的数据,0 ~ 25599 字节, 该报文的序号的值就是:0
第二个 TCP 报文段包含的是第二个 25kb 的数据,25600 ~ 51199 字节,该报文的序号的值就是:25600
......

根据 8 位 = 1 字节,那么 4 个字节可以表示的数值范围:[0, 2^32],一共 2^32 (4294967296) 个序号。
序号增加到最大值的时候,下一个序号又回到了 0.
也就是说 TCP 协议可对 4GB 的数据进行编号,在一般情况下可保证当序号重复使用时,旧序号的数据早已经通过网络到达终点或者丢失了。

确认号 Acknowledgemt Number

占 4 个字节。
表示 期望收到对方下一个报文段的序号值
TCP 的可靠性,是建立在「每一个数据报文都需要确认收到」的基础之上的。
就是说,通讯的任何一方在收到对方的一个报文之后,都要发送一个相对应的「确认报文」,来表达确认收到。
那么,确认报文,就会包含确认号
例如,通讯的一方收到了第一个 25kb 的报文,该报文的 序号值=0,那么就需要回复一个 确认报文 ,其中的确认号 = 25600.

数据偏移 Offset

占 0.5 个字节 (4 位)。
这个字段实际上是指出了 TCP 报文段的首部长度 ,它指出了 TCP报文段的数据起始处 距离 TCP报文的起始处 有多远。(注意 数据起始处 和 报文起始处 的意思)

一个数据偏移量 = 4 byte,由于 4 位二进制数能表示的最大十进制数字是 15,因此数据偏移的最大值是 60 byte,这也侧面限制了 TCP 首部的最大长度。

保留 Reserved

占 0.75 个字节 (6 位)。
保留为今后使用,但目前应置为 0。

标志位 TCP Flags

标志位,一共有 6 个,分别占 1 位,共 6 位 。
每一位的值只有 0 和 1,分别表达不同意思。

紧急 URG (Urgent)

当 URG = 1 的时候,表示紧急指针(Urgent Pointer)有效。
它告诉系统此报文段中有紧急数据,应尽快传送,而不要按原来的排队顺序来传送。
URG 要与首部中的 紧急指针 字段配合使用。

确认 ACK (Acknowlegemt)

当 ACK = 1 的时候,确认号(Acknowledgemt Number)有效。
一般称携带 ACK 标志的 TCP 报文段为「确认报文段」。
TCP 规定,在连接建立后所有传送的报文段都必须把 ACK 设置为 1。

推送 PSH (Push)

当 PSH = 1 的时候,表示该报文段高优先级,接收方 TCP 应该尽快推送给接收应用程序,而不用等到整个 TCP 缓存都填满了后再交付。

复位 RST (Reset)

当 RST = 1 的时候,表示 TCP 连接中出现严重错误,需要释放并重新建立连接。
一般称携带 RST 标志的 TCP 报文段为「复位报文段」。

同步 SYN (SYNchronization)

当 SYN = 1 的时候,表明这是一个请求连接报文段。
一般称携带 SYN 标志的 TCP 报文段为「同步报文段」。
在 TCP 三次握手中的第一个报文就是同步报文段,在连接建立时用来同步序号。
对方若同意建立连接,则应在响应的报文段中使 SYN = 1 和 ACK = 1。

终止 FIN (Finis)

当 FIN = 1 时,表示此报文段的发送方的数据已经发送完毕,并要求释放 TCP 连接。
一般称携带 FIN 的报文段为「结束报文段」。
在 TCP 四次挥手释放连接的时候,就会用到该标志。

窗口大小 Window Size

占 2 字节。
该字段明确指出了现在允许对方发送的数据量,它告诉对方本端的 TCP 接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送数据的速度。
窗口大小的值是指,从本报文段首部中的确认号算起,接收方目前允许对方发送的数据量。
例如,假如确认号是 701 ,窗口字段是 1000。这就表明,从 701 号算起,发送此报文段的一方还有接收 1000 (字节序号是 701 ~ 1700) 个字节的数据的接收缓存空间。

校验和 TCP Checksum

占 2 个字节。
由发送端填充,接收端对 TCP 报文段执行 CRC 算法,以检验 TCP 报文段在传输过程中是否损坏,如果损坏这丢弃。
检验范围包括首部和数据两部分,这也是 TCP 可靠传输的一个重要保障。

紧急指针 Urgent Pointer

占 2 个字节。
仅在 URG = 1 时才有意义,它指出本报文段中的紧急数据的字节数。
当 URG = 1 时,发送方 TCP 就把紧急数据插入到本报文段数据的 最前面 ,而在紧急数据后面的数据仍是普通数据。
因此,紧急指针指出了紧急数据的末尾在报文段中的位置。

1.3 TCP协议建立/关闭连接

本节引用自参考文献1.

1.3.1 建立连接

  • 第一次握手:客户端要向服务端发起连接请求,首先客户端随机生成一个起始序列号ISN(比如是100),那客户端向服务端发送的报文段包含SYN标志位(也就是SYN=1),序列号seq=100。
  • 第二次握手:服务端收到客户端发过来的报文后,发现SYN=1,知道这是一个连接请求,于是将客户端的起始序列号100存起来,并且随机生成一个服务端的起始序列号(比如是300)。然后给客户端回复一段报文,回复报文包含SYN和ACK标志(也就是SYN=1,ACK=1)、序列号seq=300、确认号ack=101(客户端发过来的序列号+1)。
  • 第三次握手:客户端收到服务端的回复后发现ACK=1并且ack=101,于是知道服务端已经收到了序列号为100的那段报文;同时发现SYN=1,知道了服务端同意了这次连接,于是就将服务端的序列号300给存下来。然后客户端再回复一段报文给服务端,报文包含ACK标志位(ACK=1)、ack=301(服务端序列号+1)、seq=101(第一次握手时发送报文是占据一个序列号的,所以这次seq就从101开始,需要注意的是不携带数据的ACK报文是不占据序列号的,所以后面第一次正式发送数据时seq还是101)。当服务端收到报文后发现ACK=1并且ack=301,就知道客户端收到序列号为300的报文了,就这样客户端和服务端通过TCP建立了连接。

1.3.2 断开连接

四次挥手的目的是关闭一个连接。

比如客户端初始化的序列号ISA=100,服务端初始化的序列号ISA=300。TCP连接成功后客户端总共发送了1000个字节的数据,服务端在客户端发FIN报文前总共回复了2000个字节的数据。

  • 第一次挥手:当客户端的数据都传输完成后,客户端向服务端发出连接释放报文(当然数据没发完时也可以发送连接释放报文并停止发送数据),释放连接报文包含FIN标志位(FIN=1)、序列号seq=1101(100+1+1000,其中的1是建立连接时占的一个序列号)。需要注意的是客户端发出FIN报文段后只是不能发数据了,但是还可以正常收数据;另外FIN报文段即使不携带数据也要占据一个序列号。
  • 第二次挥手:服务端收到客户端发的FIN报文后给客户端回复确认报文,确认报文包含ACK标志位(ACK=1)、确认号ack=1102(客户端FIN报文序列号1101+1)、序列号seq=2300(300+2000)。此时服务端处于关闭等待状态,而不是立马给客户端发FIN报文,这个状态还要持续一段时间,因为服务端可能还有数据没发完。
  • 第三次挥手:服务端将最后数据(比如50个字节)发送完毕后就向客户端发出连接释放报文,报文包含FIN和ACK标志位(FIN=1,ACK=1)、确认号和第二次挥手一样ack=1102、序列号seq=2350(2300+50)。
  • 第四次挥手:客户端收到服务端发的FIN报文后,向服务端发出确认报文,确认报文包含ACK标志位(ACK=1)、确认号ack=2351、序列号seq=1102。注意客户端发出确认报文后不是立马释放TCP连接,而是要经过2MSL(最长报文段寿命的2倍时长)后才释放TCP连接。而服务端一旦收到客户端发出的确认报文就会立马释放TCP连接,所以服务端结束TCP连接的时间要比客户端早一些。

1.4 确认应答机制

首先,需要理解确认应答机制;其次,需要理解:“ 确认应答机制 ” 与 “ ACK有延迟确认机制 ”之间的关系。

1.4.1 确认应答机制

每一个ACK都带有对应的确认序列号,意思是告诉发送者,我们已经收到了哪些数据,下一吃发送数据应该从哪里开始。 如上图,主机A给主机B发送了1-1000的数据,ACK应答,携带了1001序列号。告诉主机A,我已经接受到了1-1000数据,下一次你从1001开始发送数据。

1.4.2 ACK延迟确认机制

TCP协议中,接收方成功接收到数据后,会回复一个ACK数据包,表示已经确认接收到ACK确认号前面的所有数据。ACK字段长度为32位,能表示0~2^32-1之间的值。

发送方在一定时间内没有收到服务端的ACK确认包后,就会重新发送TCP数据包。发送方收到了ACK,表明接收方已经接收到数据,保证了数据的可靠达到。

接收方在接收到数据后,不是立即会给发送方发送ACK的。这可能由以下原因导致:

1、收到数据包的序号前面还有需要接收的数据包。因为发送方发送数据时,并不是需要等上次发送数据被Ack就可以继续发送TCP包,而这些TCP数据包达到的顺序是不保证的,这样接收方可能先接收到后发送的TCP包(注意提交给应用层时是保证顺序的)。

2、为了降低网络流量,ACK有延迟确认机制。

3、ACK的值到达最大值后,又会从0开始。

接收方在收到数据后,并不会立即回复ACK,而是延迟一定时间。一般ACK延迟发送的时间为200ms,但这个200ms并非收到数据后需要延迟的时间。系统有一个固定的定时器每隔200ms会来检查是否需要发送ACK包。这样做有两个目的。

1、这样做的目的是ACK是可以合并的,也就是指如果连续收到两个TCP包,并不一定需要ACK两次,只要回复最终的ACK就可以了,可以降低网络流量。

2、如果接收方有数据要发送,那么就会在发送数据的TCP数据包里,带上ACK信息。这样做,可以避免大量的ACK以一个单独的TCP包发送,减少了网络流量。

一、ACK定义
TCP协议中,接收方成功接收到数据后,会回复一个ACK数据包,表示已经确认接收到ACK确认号前面的所有数据。
ACK字段长度为32位,能表示0~2^32-1之间的值。
二、ACK作用
发送方在一定时间内没有收到服务端的ACK确认包后,就会重新发送TCP数据包。发送方收到了ACK,表明接收方已经接收到数据,保证了数据的可靠达到。
三、ACK机制
接收方在接收到数据后,不是立即会给发送方发送ACK的。这可能由以下原因导致:
1、收到数据包的序号前面还有需要接收的数据包。因为发送方发送数据时,并不是需要等上次发送数据被Ack就可以继续发送TCP包,而这些TCP数据包达到的顺序是不保证的,这样接收方可能先接收到后发送的TCP包(注意提交给应用层时是保证顺序的)。
2、为了降低网络流量,ACK有延迟确认机制。
3、ACK的值到达最大值后,又会从0开始。
四、ACK延迟确认机制
接收方在收到数据后,并不会立即回复ACK,而是延迟一定时间。一般ACK延迟发送的时间为200ms,但这个200ms并非收到数据后需要延迟的时间。系统有一个固定的定时器每隔200ms会来检查是否需要发送ACK包。这样做有两个目的。
1、这样做的目的是ACK是可以合并的,也就是指如果连续收到两个TCP包,并不一定需要ACK两次,只要回复最终的ACK就可以了,可以降低网络流量。
2、如果接收方有数据要发送,那么就会在发送数据的TCP数据包里,带上ACK信息。这样做,可以避免大量的ACK以一个单独的TCP包发送,减少了网络流量。

1.5 超时重传机制

首先,需要理解超时重传机制;其次,需要理解 “ 超时重传机制 ” 与 “ ACK有延迟确认机制 ”之间的关系。

那么发送方发送完毕后 等待的时间是多少呢? 如果这个等待的时间过长,那么会影响TCP传输的整体效率,如果等待时间过短,又会导致频繁的发送重复的包。如何权衡?

由于TCP传输时保证能够在任何环境下都有一个高性能的通信,因此这个最大超时时间(也就是等待的时间)是动态计算的。

注意:超时以500ms(0.5秒)为一个单位进行控制,每次判定超时重发的超时时间都是500ms的整数倍。 重发一次后,仍未响应,那么等待2*500ms的时间后,再次重传。等待4*500ms的时间继续重传。以一个指数的形式增长。

累计到一定的重传次数,TCP就认为网络或者对端出现异常,强制关闭连接。

1.5.1 超时重传机制

由于TCP存在一个确认应答机制,所以每次发送端发送一个数据之后,都应该收到一个ACK应答,如果没有收到,发送端就需要重新发送数据。发送端没有接收到ACK应答有可能是发送时网络拥堵没有发送出去,但也有可能对端发送来的ACK在中途丢失了,这样的话就会导致发送端重新发送重复的数据到接收端。这时TCP协议报中的序列号就起到了至关重要的作用,接收端在接收到数据之后,通过核对序列号可以起到一个去重的效果。

主机A发送数据给B之后, 可能因为网络拥堵等原因, 数据无法到达主机B; 如果主机A在一个特定时间间隔内没有收到B发来的确认应答,就会进行重发;

因此主机B会收到很多重复数据. 那么TCP协议需要能够识别出那些包是重复的包, 并且把重复的丢弃掉. 这时候我们可以利用前面提到的序列号,就可以很容易做到去重的效果.

本节仅是提供一种设计构思,没有具体实现。可以参考文献11,使用Xilinx 三速以太网MAC IP核来实现TCP/IP通信。

核心思想:

通过CTRL_LOGIC模块来控制发送接收模块的工作状态。

CTRL_LOGIC模块控制收发模块实现:“ 建立TCP连接 ” 、 “ 数据双向传输 ” 、“ ACK延迟确认 ” 、 “ 超时重传 ” 、“ 发送/接收模块数据校验 ”,通过上述这几种功能来保证FPGA通过TCP/IP与PC传输之间的可靠性!

2.1 TCP架构

2.2 TX发送模块状态控制

START状态:实现ip_head/tcp_head的组装;

TCP_DATA_CHECK:实现数据校验计算;

IP/TCP_CHECK:实现IP/TCP首部校验和计算;

SEDN_55:发送前导码

SEDN_MAC:发送MAC地址

SEND_IP_HEAD:发送IP首部

SEND_TCP_HEAD:发送TCP首部

SEND_DATA:发送数据

SEND_OPTION:发送option

SEND_CRC:发送CRC校验

2.3 CTRL_LOGIC模块状态控制

通过该模块实现对收发模块的控制,从而实现TCP的可靠传输。

本文是基于FPGA高性价比、可灵活配置的特点,也是当前流行的“微控制 器+FPGA”的嵌入式系统设计方式,所以我们提出了基于FPGA的实现方案。 本文通过在FPGA中硬件实现嵌入式 TCP IP 协议(包括UDP、 IP 、ARP、 TCP 络协议)以及以 MAC协议,并提供标准MII接口,通过外接PHY实现 络连接。 二,ZYNQ PS 的 ENET0/ENET1 通过 EMIO 的方式扩展至 PL,在 PL 中通过 RGMII 接口连接扩展子卡实现 LW IP 络通信。 在PL中搭建了1个AXI 1G/2.5G Ethernet Subsystem以及1个AXI Direct Memory Access IP 核。这两个 IP 核均通过AXI 总线经S_AXI_HP0 口与PS 连接,PS 通过AXI 总线对其进行配置和控.. 数据 传输 过程 在 络中 传输 数据 数据 包的大小依赖于链路层和物理层的 传输 能力,一般 传输 数据 的过程是 TCP 或者UDP封装 数据 数据 的头尾加上 TCP /UDP头部,之后到达 IP 络层,同样在 数据 的头部加上 IP 头部,继续链路层对 数据 加上帧头部,之后以字节的形式发送 数据 到服务端,服务端收到 数据 首先在链路层解析去掉 数据 的帧头部,再上升到... e6400: 在5001端口监听,收 数据 。 atom:从 /dev/sero 读一千兆 数据 ,发送到5001端口(注:/dev/zero文件代表一个永远输出 0的设备文件,使用它作输入可以得到全为空的文件。因此可用来创建新文件和以覆盖的方式清除旧文件) 扩展:命令学习 dd命令: - 用于读取、转换并输出 数据 。 - 可从标准输入或文件中读取 数据 ,根据指定的格式来转换 数据 ,再输出到 作者:Geoff Huston,APNIC回顾30多年来的互联 从业经验,我发现:促使互联 协议套件成功地成为全球通信系统首选技术的关键,是互联 协议( IP )本身。作为一种重叠协 议,它能够支持几乎任何类型的通信介质。但是我还想指出 IP 中另外一个重要的角色,即位于 IP 之上的可靠 传输 协议-- 传输 控制协议( TCP )。我之所以认 为它如此重要,是因为 TCP 所采用的端到端速率自适应控制 TCP 理论 上的有效带宽计算(即每秒可以 传输 多少负载 数据 ) 以千兆 为例,首先要明确千兆 的速度为1000Mbps,即每秒可 传输 1000M个bit,且这儿1M = 1000 K = 1000000。那么千兆 的速度就是125MB/s,即每秒 传输 125000000个字节。(如果按MiB计算,就是119MiB/s) 在 TCP / IP 络,一般使用以 传输 ,在以 传输 的是以 帧。而 TCP 段是封装在 IP 曾几何时,我们还在寻找 络编程中C10K问题的解决方案。现在,从硬件和操作系统支持来看,“单台服务器支持上万并发连接”已经没有多少挑战性了。 我们先假设:单台服务器最多只能支持万级并发连接。其实,这对绝大多数应用来说,已经远远足够了。但是,对于一些拥有很大用户基数的互联 公司,往往面临的并发连接数是百万、千万,甚至是上亿(百度、阿里、腾讯等公司,其 络服务 TCP 并发连接数往往会过亿)。 现在的... 曾几何时我们还在寻求 络编程中C10K问题的解决方案,但是现在从硬件和操作系统支持来看单台服务器支持上万并发连接已经没有多少挑战性了。我们先假设单台服务器最多只能支持万级并发连接,其实对绝大多数应用来说已经远远足够了,但是对于一些拥有很大用户基数的互联 公司,往往面临的并发连接数是百万,千万,甚至腾讯的上亿(注:QQ默认用的UDP协议)。虽然现在的集群,分布式技术可以为我们将并发负载分担在多台服务 在 tcp 应用中,server事先在某个固定端口监听,client主动发起连接,经过三路握手后建立 tcp 连接。那么对单机,其最大并发 tcp 连接数是多少? 如何标识一个 TCP 连接 在确定最大连接数之前,先来看看系统如何标识一个 tcp 连接。系统用一个4四元组来唯一标识一个 TCP 连接:{local ip , local port,remote ip ,remote port}。 client最大 tcp 连接数 client每次发起 tcp 连接请求时,除非绑定端口,通常会 (注:此文为经典重发,之前在EETOP公众号已推送过,看过的可以略过)(该文包含了比较多的代码,建议点击阅读原文前往论坛查看原帖)目前 TCP 协议年夜多由cpu跑代码实现, 这次用FPGA的纯逻辑实现 , System Verilog编写,下面给年夜家粗略讲一下我的实现体例,下面是工程的示意图.千兆以 TCP ,UDP协议,FPGA实现-1.jpg (31.7 KB, 下载次数: 0)2018-8... 1、修改用户进程可打开文件数限制在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发 TCP 连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统为每个 TCP 连接都要创建一个socket句柄,每个socket句柄同时也是一个文件句柄)。可使用ulimit命令查看系统允许当前用户进程打开的文件数限制:[speng@as4 ~]$ ulimit -n10...