通信系统中MAC级操作的原理
在本文中,我们将看看Engee语言中MAC(媒体接入控制)级别的基本原理,包括站间请求和响应帧的形成。 MAC层负责管理对数据传输介质的访问,并提供:
-人员编制
-错误检测和纠正
-环境访问控制
-识别车站
我们将通过声明包结构来开始示例的实现。 MacHeader 和 MacFrame 这些结构表示802.11(Wi-Fi)无线网络中的标准帧格式。 在实际实现中,可以存在取决于帧的特定类型(控制、控制或数据帧)的附加字段或变体。 我们的代码是正确的ad-hoc网络,其中 addr3 它可以是任何东西,例如, "00:00:00:00:00:00" 但是fcs在示例中仅由帧的主体计数。
MacHeader结构(MAC帧头)
/字段/*类型|/目的|
|:---|:---|:---|
|frame_control|UInt16/控制字段(帧类型、标志、协议版本)|
|duration|UInt16/用于NAV(虚拟载波感知)的信道冗余时间(μs)|
|addr1|String/**Receiver Address(RA)**是收件人的MAC。|
|addr2|String/**发送器地址(TA)**是发送器的MAC。|
|addr3|String/BSSID(在基础设施网络中,接入点的MAC,在ad—hoc—组标识符中)。|
|seq_ctrl|UInt16/序列控制|
简要说明地址的分配
- addr1(RA)-帧向谁定向(接收者)。
- addr2(TA)-谁发送帧**。
- **addr3(BSSID)**是网络标识符(对于基础设施网络,接入点的MAC)。
MacFrame结构(整个MAC帧)
| /*字段 | /*类型 | /目的 | 
|---|---|---|
| header | MacHeader/帧标题(见上文)。 | |
| body | Vector{UInt8}/有效载荷(数据)。 | |
| fcs | UInt32/帧校验序列(CRC-32)-完整性校验的校验和。 | 
struct MacHeader
    frame_control::UInt16
    duration::UInt16
    addr1::String
    addr2::String
    addr3::String
    seq_ctrl::UInt16
end
struct MacFrame
    header::MacHeader
    body::Vector{UInt8}
    fcs::UInt32
end
现在让我们继续形成请求框架。 (请求帧),它由功能 **crc32**及 create_request_frame.
第一个函数模拟数据的CRC-32(校验和)的计算,但实际上使用了一个简化的算法:它将数组中的所有字节求和,并将结果限制为32位数字(如在真正的CRC-32中)。 本CRC-32使用多项式除法(例如, 0xEDB88320).
该
第二个功能创建一个MAC请求帧(例如,通过Wi-Fi网络传输数据),让我们一步一步地看看这个功能是如何工作的。
- 
** frame_control = 0x00b4**表示是数据帧(类型 0b10)与默认标志。 在实际网络中,可能存在保护标志、碎片等。
- 
duration = UInt16(0)通道备份时间( 0-帧短,NAV不使用)。
- 
seq_num = rand(UInt16)一个随机的16位序列号(实际上,它应该递增)。 
- 
创建标题( MacHeader)- addr1-收件人的MAC(- receiver_addr).
- addr2-发件人的MAC(- sender_addr).
- addr3-BSSID(在此示例中- 00:00:00:00:00:00,这意味着ad-hoc网络)。
 
- 
frame_body = Vector{UInt8}(payload)转换字符串 payload到字节数组。
- 
fcs = crc32(frame_body)计算帧体的"校验和"(简化)。 
- 
申报表 ** MacFrame-**完成框架与标题,数据和FCS。
function crc32(data::Vector{UInt8})
    return UInt32(sum(data) % UInt32(0xFFFFFFFF))
end
function create_request_frame(sender_addr, receiver_addr, payload)
    frame_control = 0x00b4
    duration = UInt16(0)
    seq_num = rand(UInt16)
    header = MacHeader(frame_control, duration, receiver_addr, sender_addr, "00:00:00:00:00:00", seq_num)
    frame_body = Vector{UInt8}(payload)
    fcs = crc32(frame_body)
    MacFrame(header, frame_body, fcs)
end
接下来,我们将创建一个响应帧。 (Response Frame),该帧本身包括:
- 
帧头(MAC Header) 
- 
Payload,转换字符串 payload以字节为单位(Vector{UInt8}).
- 
校验和(fcs),从帧体计算CRC32。 
- 
返回成品 MacFrame头,身体和FCS。
function create_response_frame(sender_addr, receiver_addr, request_frame, payload)
    frame_control = 0x00c4
    new_duration = max(0, Int(request_frame.header.duration) - 100)
    header = MacHeader(frame_control, UInt16(new_duration), receiver_addr, sender_addr, "00:00:00:00:00:00", request_frame.header.seq_ctrl + UInt16(1))
    frame_body = Vector{UInt8}(payload)
    fcs = crc32(frame_body)
    MacFrame(header, frame_body, fcs)
end
之后,您可以继续执行用于站间交互的算法。 此测试模拟MAC帧交换在网络的两个驻地(a和B)之间。
*A-发送请求
*B-发送响应
station_a = "AA:BB:CC:DD:EE:FF"
station_b = "11:22:33:44:55:66"
request_payload = "Запрос данных от A"
request_frame = create_request_frame(station_a, station_b, request_payload)
println("Станция A отправляет кадр запроса:")
println("Кому: ", request_frame.header.addr1)
println("От: ", request_frame.header.addr2)
println("Полезная нагрузка: ", String(request_frame.body))
println("Контрольная сумма FCS: ", request_frame.fcs)
println()
response_payload = "Ответ с данными от B"
response_frame = create_response_frame(station_b, station_a, request_frame, response_payload)
println("Станция B отправляет кадр ответа:")
println("Кому: ", response_frame.header.addr1)
println("От: ", response_frame.header.addr2)
println("Полезная нагрузка: ", String(response_frame.body))
println("Контрольная сумма FCS: ", response_frame.fcs)
简单CSMA/CA协议的实现
CSMA/CA是无线网络(Wi-Fi,IEEE802.11)中使用的数据访问控制协议。 与检测到碰撞的CSMA/CD(以太网)不同,CSMA/CA通过在传输前侦听信道(载波感知)、检测到就业时的意外延迟(退避)和确认(ACK)以验证交付来防止碰撞,本示例基于较早的拆卸实现。
运算的算法
- 
渠道验证(CCA-Clear Channel Assessment) -如果通道可用→转移。 
 -如果忙→等待随机时间(退避)。
- 
退避机制 -每次尝试失败后,延迟增加(指数)。 
- 
确认(ACK) -接收方发送ACK以响应成功接收。 
- 
反复尝试 -如果ACK尚未到达→重复发送(之前 max_attempts).
接下来,让我们继续实现,第一个函数是 csma_ca_send,它模拟信道占用(rand() < 0.3 -30%的就业机会),包括退避计时器(rand(1:10) * 10 ms)当信道忙和尝试限制(max_attempts=3).
function csma_ca_send(sender, receiver, payload, max_attempts=3)
    attempt = 1
    while attempt <= max_attempts
        channel_busy = rand() < 0.3
        
        if !channel_busy
            frame = create_request_frame(sender, receiver, payload)
            println("Попытка $attempt: Кадр отправлен от $sender к $receiver")
            return frame
        else
            backoff_time = rand(1:10) * 10
            println("Попытка $attempt: Канал занят, ожидание $backoff_time мс")
            sleep(backoff_time / 1000)
            attempt += 1
        end
    end
    
    println("Не удалось отправить после $max_attempts попыток")
    return nothing
end
第二个功能是 create_request_frame 它包括一个简化的报头(没有真正的FCS,而不是有效载荷长度)和固定字段(seq_ctrl = 0xf198, addr3 = 00:00:00:00:00:00).
function create_request_frame(sender, receiver, payload)
    body_data = Vector{UInt8}(payload)
    fcs_value = length(body_data)
    return (
        header = (
            frame_control = 0x00b4,
            duration = 0x0000,
            addr1 = receiver,
            addr2 = sender,
            addr3 = "00:00:00:00:00:00",
            seq_ctrl = 0xf198
        ),
        body = body_data,
        fcs = fcs_value
    )
end
最后一个函数 receive_frame 执行收件人验证(addr1 必须匹配站的MAC地址或被广播),并且还检查校验和—FCS)-数据的长度被检查(简化)。
function receive_frame(receiver_addr, frame)
    if frame.header.addr1 != receiver_addr && frame.header.addr1 != "FF:FF:FF:FF:FF:FF"
        println("Кадр не для этой станции")
        return false
    end
    
    calculated_fcs = length(frame.body)
    if calculated_fcs != frame.fcs
        println("Кадр повреждён (несовпадение FCS)")
        return false
    end
    
    println("Кадр успешно получен:")
    println("От: ", frame.header.addr2)
    println("Данные: ", String(frame.body))
    return true
end
它与以前的版本有何不同?
- 已添加CSMA/CA(以前,立即发送帧)。
- 信道忙时的退避定时器。
- 简化的FCS(而不是CRC32,有效载荷长度)。
- 没有ACK(在真正的Wi-Fi中需要)。
接下来,我们将分析错误。
station_x = "AA:11:BB:22:CC:33"
station_y = "DD:44:EE:55:FF:66"
sent_frame = csma_ca_send(station_x, station_y, "Test data with CSMA/CA")
station_c = "CC:CC:CC:CC:CC:CC"
station_d = "DD:DD:DD:DD:DD:DD"
request = create_request_frame(station_c, station_d, "Test data")
receive_frame(station_d, request)
结论
在这个例子中,我们研究了MAC层的基本原理,用Engee语言实现请求和响应帧,基本的MAC头结构,CSMA/CA协议的简化实现和错误处理机制,并确保我们的算法正常工作。
所提供的示例演示了通信系统中MAC层的关键概念。