0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

tcp数据包接口封装的介绍

FPGA之家 来源:CSDN 作者:hasaki_code 2021-03-22 09:39 次阅读

TCP报文格式

TCP协议有着自己的数据包格式,这里把TCP的数据包称为报文段(segment),TCP报文段封装在IP数据报中发送,TCP报文段由TCP首部和TCP数据区组成,首部区域包含了连接建立与断开、数据确认、窗口大小通告、数据发送相关的所有标志和控制信息。如下图:

1c804092-8924-11eb-8b86-12bb97331649.png

首部的大小为20~60字节,在没有任何选项的情况下,首部大小为20字节,与不含选项字段的IP报首部大小相同。TCP报文中的数据部分可以为空,例如在一个连接建立或断开时,双方交换的报文段仅有TCP首部;又如当一方没有任何数据需要发送,则它需要使用不包含任何数据的报文段来发送确认信息。

1、源端口号和目的端口号两个字段用于标识发送端和接收端应用进程分别绑定的端口号。这两个值加上IP数据报首部中的源IP地址和目的IP地址就能唯一确定一个TCP连接

2、32位序号字段标识了从TCP发送端到TCP接收端的数据字节编号,它的值为当前报文段中第一个数据的字节序号。在接收方,先计算出数据区数据的长度,然后使用首部中的序号字段,就能计算出报文最后一个字节数据的序号。当建立一个新连接时,握手报文首部中的SYN标志置1,此时,序号字段包含由发送方随机选择的初始序号ISN(Initial Sequence Number)。建立连接的报文(SYN)将占用一个数据编号,因此发送方随后将要发送数据的第一个字节序号为ISN+1

3、32位确认序号只有ACK标志为1时才有效,它包含了本机所期望收到的下一个数据序号,确认常常和反向数据一起捎带发送

4、4位首部长度指出了TCP首部的长度,以4字节为单位。需要这个值是因为选项字段的长度是可变的。由于这个字段有4bit,因此TCP最多有60字节的首部,如果没有任何选项字段,首部长度应该为5(20字节)

5、在TCP首部中有6个标志bit,它们中的多个可同时被设置为1,它们告诉了接收端应该如何解释报文的内容,比如一些报文段携带了确认信息、一些报文段携带了紧急数据、一些报文包含建立或关闭连接的请求。6个标志位的意义如下图:

1d1e6826-8924-11eb-8b86-12bb97331649.png

6、窗口大小字段可看作捎带的另一个例子,窗口通告可以附加在任何报文段中发送。在TCP发送一个报文时,可在窗口字段中填写相应值以通知对方自己的可用缓冲区大小(以字节为单位),报文接收方需要根据这个值来调整发送窗口的大小。这个字段是16bit的,所以通告窗口的最大值为65535字节。窗口字段是实现流量控制的关键字段,当接收方向发送方通知一个大小为0的窗口时,将完全阻止发送方的数据发送

7、16位的紧急指针只有当紧急标志位URG置位时才有效,此时报文中包含了紧急数据,紧急数据始终放在报文段数据开始的地方,而紧急指针定义出了紧急数据在数据区中的结束处,用这个值加上序号字段值就得到了最后一个紧急数据的序号

构造TCP报文段

接下来,我们使用结构体来定义TCP报文,该结构体定义在level-ip的include/tcp.h文件中:

struct tcphdr {uint16_t sport;uint16_t dport;uint32_t seq;uint32_t ack_seq;uint8_t rsvd : 4;uint8_t hl : 4;uint8_t fin : 1,syn : 1,rst : 1,psh : 1,ack : 1,urg : 1,ece : 1,cwr : 1;uint16_t win;uint16_t csum;uint16_t urp;uint8_t data[];} __attribute__((packed));

这个结构体的成员变量,与我们刚才介绍的TCP报文格式的每个字段是一一对应的,这里不再重复解析。

tcp报文发送接口

tcp数据的发送接口tcp_transmit_skb,会在tcp建立可靠连接和数据发送时被多次调用,如三次握手、write()、read()等。在level-ip中,该接口函数保存在src cp_output.c文件中。如下图:

static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, uint32_t seq){struct tcp_sock *tsk = tcp_sk(sk);struct tcb *tcb = &tsk-》tcb;struct tcphdr *thdr = tcp_hdr(skb);/* No options were previously set */if (thdr-》hl == 0) thdr-》hl = TCP_DOFFSET;skb_push(skb, thdr-》hl * 4);thdr-》sport = sk-》sport;thdr-》dport = sk-》dport;thdr-》seq = seq;thdr-》ack_seq = tcb-》rcv_nxt;thdr-》rsvd = 0;thdr-》win = tcb-》rcv_wnd;thdr-》csum = 0;thdr-》urp = 0;if (thdr-》hl 》 5) {tcp_write_options(tsk, thdr);}tcp_out_dbg(thdr, sk, skb);thdr-》sport = htons(thdr-》sport);thdr-》dport = htons(thdr-》dport);thdr-》seq = htonl(thdr-》seq);thdr-》ack_seq = htonl(thdr-》ack_seq);thdr-》win = htons(thdr-》win);thdr-》csum = htons(thdr-》csum);thdr-》urp = htons(thdr-》urp);thdr-》csum = tcp_v4_checksum(skb, htonl(sk-》saddr), htonl(sk-》daddr));return ip_output(sk, skb);}

第12行:设置源端口号

第13行:设置目标端口号

第14行:自己发送的数据的起始序号

第15行:通知对方期望接收的下一字节的序号

在IP协议中,会对每个数据报进行编号,而在TCP中没有报文编号的概念,因为它的目标是数据流传输,数据流由连续的字节流组成,尽管在上层可能用各种各样的数据结构和格式来描述数据,但在TCP看来,数据都是字节流。TCP把一个连接中的所有数据字节都进行了编号,当然两个方向上的编号是彼此独立的,编号的初始值由发送数据的一方随机选取,编号取值是0~2^32-1,比如发送方选择的起始编号为20,且将要发送的数据长度为800字节,那么字节编号将覆盖20到819的范围。当所有字节被编上号后,字节流会被分装在若干个TCP报文中发送,此时TCP报文首部的字段能够记录它所运载数据的起始编号以及运载数据的长度。在接收端,可以根据这些信息对报文中数据进行排序和确认。例如,将上述的800字节放在三个报文段中来发送,前两个报文段各装载了300字节的数据,最后一个报文装载了200字节的数据,则三个报文段携带的数据情况如下:

报文段1:起始序号:20,数据长度:300,序号范围:20~319

报文段2:起始序号:320,数据长度:300,序号范围:320~619

报文段3:起始序号:620,数据长度:200,序号范围:620~819

接收方通过确认的机制来告诉发送方数据的接收状况,这是通过向发送方返回一个确认号来完成的,确认号标识出自己期望接收到的下一个字节的编号,例如在上面的例子中,如果接收方接收到了报文段1,则它返回给发送方的确认号为320,表示自己期望收到数据编号为320的数据;确认号是累计的,即如果发送方接收到确认号的值为620,说明接收方已经正确接收了620编号以前的所有数据,接收方可能是在收到两个报文段后才发送的一个确认;还有一种情况,如果接收方只收到报文段1和3,那么它返回的确认号仍然是320,确认号始终表示接收方期望的下一字节数据,尽管可能已有更高编号的数据被收到

第16行:保留位

第17行:设置滑动窗口大小

在数据发送端,所有数据流按照顺序被组织在发送缓存中,什么时候发送数据以及发送的多少是由滑动窗口决定的,使用窗口滑动的概念可以达到很好的流量控制效果和拥塞控制效果。如下图所示,滑动窗口可以看成定义在数据缓冲上的一个窗口,缓冲中存放了从应用程序传递过来的待发送数据,窗口能在缓冲上滑动,滑动窗口状态决定了TCP能发送哪些数据。滑动窗口较大时, TCP可以在收到确认之前一次性地发送几个报文段,这样,可以使得网络总是处于忙碌状态,提高网络的吞吐率。当发送窗口较小时,能够被发送的报文很少,在极端情况下,当发送窗口为0时,没有任何报文能被发送,减少报文的发送是进行拥塞控制的最直接手段。因此,流量控制和拥塞控制的本质在于对发送窗口的合理调节

第18行:校验和设置为0

第19行:紧急指针设置为0,

TCP采用了缓冲机制来保证协议的高效性,在数据发送时,TCP内核将延迟小分组数据的交付,它将等待足够长的时间,以期待接收更多的应用数据,最后再一起发送;在接收数据时,TCP首先是先将数据放在接收缓冲中,只有在应用程序准备就绪或者TCP协议认为时机恰当的时候,数据才会被交付给应用程序。上述缓冲机制是出于对网络性能提升的考虑,但是它可能会妨碍某些应用程序的使用。例如,两个应用程序进行交互式通信,一端应用程序打算把用户键入的字符发送给另一端应用程序,并且期望对方立即响应。在这种情况下,TCP的数据收集与延迟发送、缓冲递交会给用户带来很不好的体验。为了满足交互式应用场合的需求,TCP可以采用下面的方式解决这个问题。发送方应用程序向TCP传递数据时,请求推送(push)操作,这时,TCP协议不会等待发送缓冲区被填满,而是直接将报文发送出去。同时,被推送出去的报文首部中推送位(PSH)将被置1,接收端在收到这类报文时,会尽快将数据递交给应用程序,而不必缓冲更多的数据再递交

tcp接收接口

tcp数据接收接口为tcp_in()函数。该函数在ip数据帧读取接口ip_rcv()函数中调用。该函数保存在srcip_input.c文件中,我们来了解一下这个函数,如下图:

void tcp_in(struct sk_buff *skb){struct sock *sk;struct iphdr *iph;struct tcphdr *th;iph = ip_hdr(skb);th = (struct tcphdr*) iph-》data;tcp_init_segment(th, iph, skb);sk = inet_lookup(skb, th-》sport, th-》dport);if (sk == NULL) {print_err(“No TCP socket for sport %d dport %d ”,th-》sport, th-》dport);free_skb(skb);return;}socket_wr_acquire(sk-》sock);tcp_in_dbg(th, sk, skb);/* if (tcp_checksum(iph, th) != 0) { *//* goto discard; *//* } */tcp_input_state(sk, th, skb);socket_release(sk-》sock);}

第7行:从sk_buff中读取ip首部信息

第8行:从ip数据包的data区域中读取tcp数据信息

第10行:进行关键字段的大小端变换和计算应答序号等

第12行:根据通信端口,查找管理该次tcp连接的结构体sock

第20行:获取该结构体的读写锁

第26行:数据递交给tcp_input_state()函数处理,该函数会进行tcp通信状态的变化,以及获取把整理好的有序报文递交给应用程序。

总结

在对可靠性要求很高的场合下,使用TCP提供的传输性能是很合适的,TCP将两个进程间传递的数据看作数据流的形式,两个先后发出的TCP报文虽然在网络中也是互不相关的传输,但是它们携带的数据之间却具有关联关系,因为TCP给传输的每个字节数据一个唯一的编号。在接收端,所有数据将按照编号被顺序组织起来,当所有数据接收成功后,TCP才把数据递交给应用层。应用层不必担心报文的乱序、重复、丢失等问题,TCP采用正面确认以及超时重传等机制保证数据流能全部正确到达。

但是,我们这篇文章还没涉及到这部分的内容,但是我们已经找到分析的突破口,那就是上面所提到的tcp_input_state()函数,以后我们将在该函数里面剖析tcp种种可靠性机制。

原文标题:level-ip之tcp数据包接口封装

文章出处:【微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据
    +关注

    关注

    8

    文章

    7026

    浏览量

    89021

原文标题:level-ip之tcp数据包接口封装

文章出处:【微信号:zhuyandz,微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    mtu配置步骤详解 mtu与数据包丢失的关系

    MTU(Maximum Transmission Unit)即最大传输单元,是指一种通信协议的某一层上面所能通过的最大数据报大小,单位是字节。MTU配置步骤及其与数据包丢失的关系如下: MTU配置
    的头像 发表于 12-16 14:33 516次阅读

    艾体宝干货 OIDA之四:掌握数据包分析-分析的艺术

    本文是OIDA方法系列的最后一部分,重点介绍数据包分析的“分析”阶段。这一最后阶段将剖析阶段的精炼数据转化为可操作的见解,使网络管理员和安全专业人员能够解决问题、优化性能并增强安全性。分析是实现
    的头像 发表于 09-24 11:47 196次阅读
    艾体宝干货 OIDA之四:掌握<b class='flag-5'>数据包</b>分析-分析的艺术

    请问DCTCP与DCUDP 的登录数据包和心跳数据包与服务器端是如何交互的?

    DCTCP与DCUDP的登录数据包和心跳数据包与服务器端是如何交互的?
    发表于 07-25 06:37

    使用AT SAVETRANSLINK时UDP数据包丢失怎么解决?

    Android 发送一个小 UDP 数据包(5 字节)。这个小数据包被我的微控制器在UART上接收到。微控制器将更大的数据包(可变长度,约 100 字节)发送回 UART。ESP在UART上接
    发表于 07-18 07:17

    能否在ESP结束之前通过串行端口停止传入的UDP数据包的传输以解析下一个UDP数据包

    我正在做一个artnet节点, 它收到几个 UDP 广播数据包,工作正常,但是: 其中一些必须使用,其中一些必须丢弃, mi问题是:所有传入的数据包都出现在带有IPD命令的串行端口上, 并且我需要
    发表于 07-16 06:18

    请问如何使用AT CIPSEND或AT CIPSENDBUF发送多个数据包

    我可以使用 AT CIPSEND 发送单个数据包。但是我必须发送一系列二进制数据包。如何使用AT CISEND或AT CIPSENDBUF发送多个数据包,什么是正确的算法? 到目前为止,我尝试
    发表于 07-15 07:37

    TCP传输大量数据时丢失数据的原因?

    TCP用于传输大量数据时,要找到数据丢失的地方,当TCP传输大量数据时,数据包丢失,
    发表于 07-12 15:03

    esp8266是否可以在station和AP接口之间转发ip数据包

    esp8266 是否可以在 station 和 AP 接口之间转发 ip 数据包?有人试过吗?如果我们想将 esp 用作互联网或类似事物的网关,那么实施这将是一件非常有帮助的事情。
    发表于 07-10 07:49

    ESP32-C3在SPI-AT模式下进行数据透传,最后一个数据包数据偶尔会出现错误,为什么?

    目前采用SPI-AT的方式在两个硬件板之间进行数据的无线传输,一个作为AP开启TCP服务器,一个作为STA连接到对应的服务器,传输的数据量为3000000字节,在测试的过程中偶尔会出现数据
    发表于 06-26 06:07

    在AN65974中短数据包和零长数据包是什么意思?

    在 AN65974 中,短数据包和零长数据包是什么意思? 非常感谢!
    发表于 05-30 07:41

    如何在AIROC GUI上获取良好数据包和总数据包

    使用 IQxel-MW LifePoint 作为发生器并发送波形BT_1DH5_00001111_Fs80M.iqvsg,但无法在 AIROC 工具中接收数据包。 以下是从 IQxel 发送
    发表于 05-22 06:39

    请问高端网络芯片如何处理数据包呢?

    随着网络芯片带宽的持续提升,其内部数据包处理单元的工作负载也随之增加。然而,如果处理单元无法与网络接口的传入速率相匹配,将无法及时处理数据包,这不仅会导致数据包随机丢失,更会降低网络的
    的头像 发表于 04-02 16:36 630次阅读
    请问高端网络芯片如何处理<b class='flag-5'>数据包</b>呢?

    STM32H7接收数据包异常,一接收的数据出现两发送的内容怎么解决?

    );__HAL_UART_DISABLE_IT( huart1, DMA_IT_HT); 2、发送数据包1
    发表于 03-08 08:05

    DPDK在AI驱动的高效数据包处理应用

    传统的数据包处理方式是数据包先到内核最后再到用户层进行处理。这种方式会增加额外的延迟和CPU开销,严重影响数据包处理的性能。 DPDK 绕过内核,在用户空间中实现快速数据包处理。
    的头像 发表于 02-25 11:28 939次阅读
    DPDK在AI驱动的高效<b class='flag-5'>数据包</b>处理应用

    使用P4和Vivado工具简化数据包处理设计

    电子发烧友网站提供《使用P4和Vivado工具简化数据包处理设计.pdf》资料免费下载
    发表于 01-26 17:49 0次下载
    使用P4和Vivado工具简化<b class='flag-5'>数据包</b>处理设计