【数据链路层】封装成帧和透明传输和差错控制

简介: 【数据链路层】封装成帧和透明传输和差错控制

注:最后有面试挑战,看看自己掌握了吗

🍃博主昵称:一拳必胜客

🌸博主寄语:欢迎点赞收藏关注哦,一起成为朋友一起成长;

特别鸣谢:木芯工作室 、Ivan from Russia


前言

  1. 功能+应用

链路层功能

  1. 封装成帧—链路层
  2. 传比特-----物理层
  3. 加头加尾封装----------链路层
  4. 节点—主机、路由器,
  5. 链路–物理通道
  6. 数据链路----逻辑通道
  7. 帧----封装网络数据包—链路层
  8. 可靠的传输到相邻节点
  9. 给网络层提供无差错的服务
  10. 加强物理层传输原始比特流功能

功能

  1. 为网络层提供服务—无确认无连接服务、有确认无连接服务、有确认有链接服务
  2. 链路管理:连接的建立维持释放------有连接服务
  3. 组帧
  4. 流量控制-----限制发送方
  5. 差错控制—帧错/位错

封装成帧和透明传输

  1. 把网络层IP数据报加头加尾形成帧
  2. 帧首部、尾部
  3. 这个作用叫:帧定界服务
  4. 帧同步----接收方可以区分出 头、尾
  5. 最大传送单元MTU

组帧的四种方法

  1. 字符集书法—用帧首部的第一个字节来标明帧内字符数-----痛点:鸡蛋装在一个篮子–一错全错,失去同步
  2. 字符填充法— SOH---------EOT -------1当传送文本字符文件非常好用----透明传输2采用字符填充法,加上转义字符ESC不去管数据当中的数据信息
  3. 零比特填充法------方法:5"1"1"0"-------连续的5个1添0
  4. 违规编码法--------曼彻斯特编码,用高-高,低-低来界定帧的起始终止------局域网IEEE就用这种方法

透明传输

  1. 链路层好像看不到这样的信息
  2. 单纯传送数据到目标

差错控制

检错编码

  1. 插错都是由噪声引起的
  2. 全局性:线路本身电气特性所产生的随机噪声,是信道固有的、随即存在。---------------解决办法:提高信噪比或者避免干扰
  3. 局部性-----外部短暂原因造成的冲击噪声--------是产生差错的主要原因-----------利用编码技术拉解决

差错

  1. 位错—比特位错误
  2. 帧错—帧丢失、帧重复、帧失序
  3. 当通信质量好有线传输链路----------无确认无连接--------传输层来保证可靠传输
  4. 通信质量差的无线传输-----------有确认有链接
  5. ------------------因材施教

链路层的差错控制

检错编码

  1. 奇偶校验码—1的个数的奇偶------检错能力50%
  2. 循环冗余码CRC------数据发送之前,按照某种关系附加一定冗余位
  3. 要传的数据 / 生成多项式= *** ----------PSC帧检测序列/冗余码
  4. 接收端:接收到的数据 / 生成多项式 = *** -----------0
  5. 最终发送的数据: 要发送的数据+帧检验序列FCS
  6. 计算冗余码:1.加0 2.模二除法(异或)
  7. TIP 多项式N位,阶位N-1位
  8. 硬件实现-----迅速
  9. “凡是接收端数据链路层接收的帧均无差错”
  10. 这仍然是不可靠传输 ----有丢弃的帧,没有进行处理

纠错编码

  1. 海明码
  2. 码距----海明距离-------一个编码的系统里面任意两个合法编码之间的最小距离
  3. 看码距-----就是直接眼看--------另种方法就是异或
  4. 码距:n--------检错能力:n-1
  5. 所以,码距是3检错能力2
  6. 海明码
  7. 数据m位,校验码r位
  8. 校验码取值有2的r次方种取值
  9. 2的r次方>=m+r+1----------------海明不等式----------确定校验码位数-------直接带入尝试r--------加的1是正确情况
  10. 校验码放在2的n次方位置上------------一个个算1 2 4 8
  11. 通配形式 1 ** ---------负责所有1开头的检测 ------如101
  12. 求出校验码的值:采用偶校验,1号校验码负责1,3,5,7的校验
  13. 2号位负责2 3 6 7
  14. 4号校验码负责:4 5 6 7
  15. 我们把出错的找出来,然后把对的排除出来--------找出那个错的
  16. 纠错方法2:把那些校验码都写出来 x4 x2 x1-------101------第五位出错

链路层代码实现

//Ethernet.h
//这里只为上次的Ethernet.h做一补充
int is_accept_ethernet_packet(u_int8_t *packet_content, int len);
void ethernet_protocol_packet_callback(u_char *argument, const struct pcap_pkthdr *packet_header, const u_char *packet_content);
//Ethernet.cpp
#include "Network_IPV4_recv.h"
#include "Network_ARP_recv.h "
//这里需要调用上层提供的接收函数接口交付数据包
int is_accept_ethernet_packet(u_int8_t *packet_content, int len)
{
    struct ethernet_header *ethernet_hdr = (struct ethernet_header *)packet_content;
    int i;
    int flag = 0;
    //检查目的MAC地址是否是广播MAC地址
    for (i = 0; i < 6; i++)
    {
        if (ethernet_hdr->destination_mac[i] != 0xff)break;
    }
    if (i == 6)
    {
        flag = 1;
        printf("It's broadcast packet.\n");
    }
    //检查目的MAC地址是否是本地MAC地址
    for (i = 0; i < 6; i++)
    {
        if (ethernet_hdr->destination_mac[i] != local_mac[i])break;
    }
    if (i == 6)
    {
        flag = 1;
        printf("It's sended to my pc.\n");
    }
    //若上边检查均未通过,返回0表示本数据包不需要接收
    if (!flag)
        return 0;
    //否则检查CRC校验码
    u_int32_t crc = calculate_crc((u_int8_t *)packet_content , len - 4 );
    if (crc != *((u_int32_t *)(packet_content + len - 4)))
    {
        printf("The data has changed.\n");
        return 0;
    }
    //CRC无误则本数据包可以接收,返回1
    return 1;
}
//接收数据帧的回环函数
void ethernet_protocol_packet_callback(u_char *argument, const struct pcap_pkthdr *packet_header, const u_char *packet_content)
{
    int len = packet_header->len;
    if (!is_accept_ethernet_packet((u_int8_t *)packet_content, len))
    {
        return;
    }
    struct ethernet_header *ethernet_hdr = (struct ethernet_header *)packet_content;
    u_int16_t ethernet_type = ntohs(ethernet_hdr->ethernet_type);
    //去掉MAC帧首部,将数据部分根据上层协议交付给相应的上层接收函数
    u_int8_t *upper_buffer = (u_int8_t *)(packet_content + sizeof(ethernet_header));
    switch (ethernet_type)
    {
    case 0x0800:
        printf("Upper layer protocol: IPV4\n");
        network_ipv4_recv(upper_buffer);
        break;
    case 0x0806:
        printf("Upper layer protocol: ARP\n");
        dest_mac=network_arp_recv(upper_buffer);
        break;
    case 0x8035:
        printf("Upper layer protocol: RARP\n");
        //network_rarp_recv();
        break;
    case 0x814c:
        printf("Upper layer protocol: SNMP\n");
        //network_snmp_recv();
        break;
    case 0x8137:
        printf("Upper layer protocol: IPX(Internet Packet Exchange)\n");
        //network_ipx_recv();
        break;
    case 0x86DD:
        printf("Upper layer protocol: IPV6\n");
        //network_ipv6_recv();
        break;
    case 0x880B:
        printf("Upper layer protocol: PPP\n");
        //network_ppp_recv();
        break;
    default:break;
    }
    //以上注释掉的协议均未实现,有兴趣的伙伴可以在看完我的协议栈设计的基础上在进行追加
}

到这里我们就算介绍完了数据链路层以太网的数据包发送和接收的过程及实现,我们先在此简单总结一下:

我们的数据发送向上层提供的接口函数是:

int ethernet_send_packet(u_int8_t *upper_buffer,u_int8_t
 *destination_mac,u_int16_t ethernet_type)

上层调用此函数时需要提供的参数有:

1、上层的数据包,即链路层数据帧的数据部分

2、数据包长度,这里我们用全局变量ethernet_upper_len来获取 2、目的MAC地址

3、调用此函数的上层协议

数据接收时,根据上层协议不同提交时上层提供给我们的接口有:

network_arp_recv(upper_buffer);
 network_ipv4_recv(upper_buffer); //这两个我们后边会慢慢给大家展示出来


相关文章
|
Python
Python网络编程基础(Socket编程)绑定地址和端口
【4月更文挑战第9天】在UDP服务器编程中,我们首先需要创建一个UDP套接字,然后绑定一个本地地址和端口,以便客户端可以通过这个地址和端口与我们的服务器进行通信。下面,我们将详细讲解如何绑定地址和端口。
解决办法:gpg : 从公钥服务器接收失败:公钥服务器错误
解决办法:gpg : 从公钥服务器接收失败:公钥服务器错误
8876 0
|
11月前
|
存储 弹性计算 安全
阿里云服务器2核8G与4核16G配置选购参考:价格、性能及适用场景
2核8G、4核16G配置是很多个人和企业用户搭建网站和中小型数据库系统等场景时首选的云服务器配置,现在购买2核8G配置最低年付价格只要652.32元/1年,4核16G配置短期租用可以选择月付,现在89元即可购买到经济型e实例4核16G10M带宽配置1个月,年付选择通用算力型u1实例价格为1196.64元/1年起。本文为大家解析阿里云服务器2核8G与4核16G配置的租用费用,热门实例适用场景,以供参考和选择。
|
11月前
|
存储 监控 数据可视化
淘宝API实时竞品监控,市场策略快人一步!
在电商竞争中,实时掌握竞品动态至关重要。本文详解如何利用淘宝开放API构建竞品监控系统,实现价格、库存、促销等数据的自动化采集与分析,帮助企业快速响应市场变化,优化定价、促销与库存策略,提升市场竞争力。
|
安全 Java 数据安全/隐私保护
Spring Security 6.x 一文快速搞懂配置原理
本文主要对整个Spring Security配置过程做一定的剖析,希望可以对学习Spring Sercurity框架的同学所有帮助。
1286 5
Spring Security 6.x 一文快速搞懂配置原理
|
网络架构 Python
在Flask中,如何定义路由并处理HTTP请求的不同方法(GET、POST等)?
【4月更文挑战第25天】在Flask中,使用`@app.route()`装饰器定义路由,如`/hello`,处理GET请求返回&#39;Hello, World!&#39;。通过添加`methods`参数,可处理不同HTTP方法,如POST请求。单一函数可处理多种方法,通过检查`request.method`区分。动态路由使用 `&lt;variable_name&gt;` 传递URL变量到视图函数。这些基础构成处理HTTP请求的Flask应用。
638 1
|
网络协议 网络架构
字节填充与0比特填充以及数据链路的基本问题
字节填充与0比特填充以及数据链路的基本问题
1632 0
|
算法 Java 开发工具
Android 编译C++
Android 编译C++
455 0
|
网络协议 Java Windows
【Minecraft开服】Windows搭建我的世界MC服务器「公网远程联机」
简单几步在windwos搭建我的世界服务器,并通过cpolar工具将本地服务暴露到公网连接
6921 0
【Minecraft开服】Windows搭建我的世界MC服务器「公网远程联机」
|
前端开发 Java 测试技术
SpringBoot测试——高级配置
SpringBoot测试——高级配置
354 0