Python使用原始套接字发送二层包(链路层帧)的方法
本文介绍如何在Python中使用原始套接字(Raw Socket)发送链路层(二层)数据包。通过设置PF_PACKET和SOCK_RAW,自定义协议类型如0x1234,并手动构造包含目的MAC、源MAC及协议类型的以太网头部。文章提供发送端与接收端的完整代码示例,演示如何绑定网卡、打包数据及接收处理,适用于网络协议分析与底层通信开发。
Python原始套接字发送二层帧实现
发送端代码实现如下:
发送端代码详解
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import socket
import struct
raw_socket = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.htons(0x1234))
raw_socket.bind(("eth0", 0))
packet = struct.pack("!6s6sH", "\xff\xff\xff\xff\xff\xff", "\xaa\xaa\xaa\xaa\xaa\xaa", 0x1234)
while True:
print repr(packet)
raw_socket.send(packet + "hello,world!")
首先,创建套接字时需指定地址家族为PF_PACKET,类型设为SOCK_RAW,并自定义协议类型为0x1234,这与C语言中的用法一致。若选择使用0X0800(即ETH_P_IP),则需自行填充IP头部和MAC头部以模拟IP包。此处采用0x1234这一系统未定义的协议类型,以便在特定场景下进行测试或自定义通信。
由于发送的是二层数据包,且默认网卡未配置网络层地址(即无法通过ping连通),因此直接将套接字绑定到指定网卡接口上。
在Linux内核中,以太网头部结构定义如下:
以太网头部结构分析
struct ethhdr
{
unsigned char h_dest[6];
unsigned char h_source[6];
uint16_t h_proto; //0x1234
};
该结构包含目的MAC地址、源MAC地址以及协议类型字段。其中,协议类型必须正确填写,以确保接收方在识别到该自定义类型时,能将数据包正确交付给对应的套接字。利用struct模块中的pack函数,格式字符串为“!6s6sH”,分别对应6字节的目的MAC、6字节的源MAC以及2字节的协议类型。本例中使用广播地址(全F)进行发送。接收端代码实现如下:
接收端代码示例
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import socket
import struct
raw_socket = socket.socket(socket.PF_PACKET,socket.SOCK_RAW,socket.htons(0x1234))
while True :
packet = raw_socket.recv(1024)
data = struct.unpack("!6s6sH12s", packet)
print repr(data[0])
print repr(data[1])
print repr(data[2])
print repr(data[3])
以上关于Python使用原始套接字发送二层包(链路层帧)的方法即为完整分享内容,供读者参考与实践,欢迎支持相关技术社区。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









