首页 > 其他分享 >从0写TCPIP协议栈3:以太网包的收发实现

从0写TCPIP协议栈3:以太网包的收发实现

时间:2023-02-04 20:11:36浏览次数:41  
标签:return packet 收发 rsize 包头 eth 数据包 以太网 TCPIP

协议传输机制

WEB服务器和客户计算机得交互过程简述如下:

1、应用层协议栈软件将文件数据进行提取封装,并添加HTTP协议报头向传输层进行传输

2、传输层协议栈软件在上层传递下来得数据包基础上继续添加TCP报头向链路层进行传输

3、链路层协议栈软件在上层传递下来得数据包基础上继续添加IP头/IP地址然后通过以太网接口将逻辑信号转为物理链路得物理信号

4、客户计算机提取物理链路上得物理型号并进行逻辑信号转换,然后依次剔除各层报头,一直往客户计算机应用层传递

包的结构

从上面的交互流程来看,主机和服务器交互时最重要的不是文件文本的数据,而是各层协议的包头,那定义包头需要考虑的核心问题就是:需要各层协议栈软件支持对应包头和不通数据长度包处理。

那可以简单定义为下面的数据包结构:包的有效长度+指向添加包头的指针+文件数据,那可以定义为一个结构体:

/*定义以太网包的成员及相关参数*/
#define PACKET_SIZE 1516 //以太网链路的最大就是1514,考虑CRC则是1516
typedef struct _eth_packet
{
	uint16_t size;//包大小
	uint8_t* dataptr;//指向包头的指针
	uint8_t payload[PACKET_SIZE];//存放文本数据和各协议栈包头
}_eth_packet;

_eth_packet tx_packet;
_eth_packet rx_packet;

操作包

在定义好基本的数据包格式后,我们需要定义数据包的发送、接收、包头增加、包头移除四个最基本的函数,至于包中实际数据的操作,我们在说到各协议时再提:

数据包发送与接收

/*
brief:处理tx的数据
return:返回处理好的数据地址指针
*/
_eth_packet* tx_xnet_packet(_eth_packet* eth_packet, uint16_t rsize)
{
	eth_packet->dataptr = tx_packet.payload + PACKET_SIZE;
	eth_packet->size = rsize;
	return eth_packet;
}

/*
brief:处理rx的数据
return:返回处理好的数据地址指针
*/
_eth_packet* rx_xnet_packet(_eth_packet* eth_packet, uint16_t rsize)
{
	//分配文件的缓冲空间
	eth_packet->dataptr = eth_packet->payload;//直接指向数据包的地址
	eth_packet->size = rsize;
	return eth_packet;
}

需要注意几个点,首先我们不可以将struct eth_packet按值传递,如果想要按值传递,请将你得数据包声明为static,例如:

static _eth_packet tx_packet;
static _eth_packet rx_packet;

其次就是指针的移动方向需要设置为<<,这是因为以太网的数据包总是增删包头,因此将包尾视为指针基地址比较合理,此操作在包头的增删函数中会有体现。

包头的增删

/*
brief:添加包头
return:返回处理好的数据地址指针
*/
_eth_packet* add_header(_eth_packet* eth_packet, uint16_t rsize/*包头大小*/)
{
	eth_packet->dataptr -= rsize;//包中首个数据的地址
	eth_packet->size += rsize;//数据长度=原本数据长度+包头大小
	return eth_packet;
}

/*
brief:去除包头
return:返回处理好的数据地址指针
*/
_eth_packet* del_header(_eth_packet* eth_packet, uint16_t rsize)
{
	eth_packet->dataptr += rsize;
	eth_packet->size -= rsize;
	return eth_packet;
}

可以看出在add_header()中的eth_packet->dataptr -= rsize;正是基于包指针地址为结尾的思想去实现的。

包的截取

在操作eth_packet.payload[]数据前我们首先需要检查包的数据长度是否合理,过长则需要截取然后立即转发,这一思想和Autosar-PDUR中的gatingway-on-fly类似,本次练习我们只截取,不做分批发送:

_eth_packet* truncate_header(_eth_packet* eth_packet, uint16_t rsize)
{
	eth_packet->size = ((eth_packet->size)>(rsize)) ? rsize : eth_packet->size;//取最小值
	return eth_packet;
}

以太网驱动封装

标签:return,packet,收发,rsize,包头,eth,数据包,以太网,TCPIP
From: https://www.cnblogs.com/YiMo9929/p/17092244.html

相关文章

  • 从0写TCPIP协议栈2:开发概述
    开发概述:协议栈框架介绍在正式开发前,先将本次的目标框架介绍下:本次需要在Windows环境下基于C++语言实现一个简单的:Web服务器协议栈框架+客户计算机协议栈框架+网页设计......
  • STM32 UART收发-中断方式接收-重定向printf函数
    STM32UART串口收发与中断方式接收扫描以下二维码,关注公众号​​雍正不秃头​​获取更多STM32资源及干货!环境:1、STM32CubeMX5.32、AtollicTrueSTUDIOforSTM329.3.03......
  • 以太网TYPE类型
    前导码:EthernetII是由8个8‘b10101010构成,IEEE802.3由7个8‘b10101010+1个字节SFD​目的地址:目的设备的MAC物理地址。源地址:发送设备的MAC物理地址。类型(EthernetII):以......
  • tcp/ip详解之04 以太网和802.3封装
    1.以太网和802.3封装在TCP/IP世界中,以太网IP数据报的封装是在RFC894[Hornig1984]中定义的,IEEE802网络的IP数据报封装是在RFC1042[PostelandReynolds1988]中定义的。......
  • 网桥、集线器和以太网交换机
    一:网桥(bridge)网桥又叫做桥接器,工作在数据链路层,是一个二层设备。1.网桥的作用:1、网桥在数据链路层上实现局域网互连;2、网桥能够互连两个采用不同传输介质与......
  • 什么是以太网
    一:什么是以太网:以太网是一种局域网技术,以太网是一种用于数据链路层的协议类型。二:以太网的由来:以太网是美国施乐(Xerox)公司的PaloAlto研究中心(简称为PARC)于1975年研......
  • FMC子卡设计资料原理图:FMC550-基于ADRV9002双窄带宽带射频收发器FMC子卡
    FMC550-基于ADRV9002双窄带宽带射频收发器FMC子卡   一、产品概述  ADRV9002 是一款高性能、高线性度、高动态范围收发器,旨在针对性能与功耗系......
  • 虚拟串口及其在串口转以太网中的应用
    ​ 本文介绍虚拟串口的概念,以及如何在串口转以太网中利用该技术。1.虚拟串口的概念虚拟串口是用操作系统的虚拟驱动技术产生的串口(COM口),相对于计算机本身的硬件串口(COM......
  • 华普物联HP-EAIO-244关于大棚智能控制系统,RS485转RJ45工业以太网,TCP Client,Modbus TC
    很多蔬菜、花卉、林木等植物栽培或育苗都需要在温室里进行,温室,又称暖房。能透光、保温(或加温),用来栽培植物的设施。在不适宜植物生长的季节,能提供温室生育期和增加产量,多用......
  • 基于SpringBoot 使用 Flink 收发Kafka消息
    前言这周学习下Flink相关的知识,学习到一个读写Kafka消息的示例,自己动手实践了一下,别人示例使用的是普通的JavaMain方法,没有用到springboot.我们在实际工作中会使用spr......