我将首先说明我对网络和整个 OSI 模型知之甚少。
我的目标是使用非托管网络交换机创建一个小型网络(现在是我的笔记本电脑和树莓派)。在更高层传输(级别 3+)上,我只需为数据包设置目标 IP 地址。根据我在 Wikipedia 上阅读的内容,网络交换机在数据链路层运行,这意味着它使用 MAC 地址。
当与仅支持 MAC 地址的设备连接时,如何将数据发送到局域网上的设备。更重要的是,如何使用 Java 或 C# 等高级语言来做到这一点?
我将首先说明我对网络和整个 OSI 模型知之甚少。
我的目标是使用非托管网络交换机创建一个小型网络(现在是我的笔记本电脑和树莓派)。在更高层传输(级别 3+)上,我只需为数据包设置目标 IP 地址。根据我在 Wikipedia 上阅读的内容,网络交换机在数据链路层运行,这意味着它使用 MAC 地址。
当与仅支持 MAC 地址的设备连接时,如何将数据发送到局域网上的设备。更重要的是,如何使用 Java 或 C# 等高级语言来做到这一点?
Liam Kelly 的回答对数据发送的抽象提供了深刻的见解。我将尝试提供补充信息。
虽然大多数交换机在数据级别运行,但有些交换机可以在更高级别执行某些操作:
第 3 层:在以太网物理层的范围内,第 3 层交换机可以执行通常由路由器执行的部分或全部功能。
第 4 层:[...] 网络地址转换功能,但随后添加了基于 TCP 会话的某种类型的负载分配。
第 7 层:[...] 基于统一资源定位器 (URL) 分配负载,或者通过使用某些特定于安装的技术来识别应用程序级事务。
如前所述,这些需要相当高级的编程技能。由于安全问题,它们在现代 Windows 操作系统(源)的非服务器版本中也受到严格限制:
- TCP 数据不能通过原始套接字发送。
- 无法通过原始套接字发送具有无效源地址的 UDP 数据报。任何传出 UDP 数据报的 IP 源地址必须存在于网络接口上,否则数据报将被丢弃。进行此更改是为了限制恶意代码创建分布式拒绝服务攻击的能力,并限制发送欺骗数据包(具有伪造源 IP 地址的 TCP/IP 数据包)的能力。
- 不允许使用 IPPROTO_TCP 协议的原始套接字调用绑定函数。
如果 .NET 对您来说是一个可行的选择,我会尝试 Pcap.Net,因为它允许使用高级编程(包括 LINQ)在数据包级别进行各种操作。
TL;DR OSI 模型是关于抽象的,编程语言使用操作系统调用来实现这种抽象。Rasberry Pi 正在运行完整的操作系统,并将发送和接收寻址到其分配的 IP 地址的网络数据。您不需要指定 MAC 地址。
您想通过笔记本电脑与 Raspberry Pi 进行通信。为此,您首先将它们连接到哑交换机,并在连接到哑交换机的物理接口上为两个设备分配同一子网中的 IP 地址。假设您的笔记本电脑的物理以太网连接已分配10.0.0.1/24
,并且 Rasberry Pi 的物理以太网连接已分配10.0.0.2/24
(如果您不理解我的符号,请查看CIDR)。IP 地址是第 3 层结构。现在,您的应用程序将使用操作系统套接字创建具有第 4 层地址(应用程序端口)的 TCP 或 UDP 连接(请参阅此处的 UDP java 示例)。高于第 4 层的所有内容都由您的应用程序处理。
第 2 层及更低层由操作系统处理。当您的应用程序尝试通过套接字发送数据时,操作系统会通过查看目标 IP 地址来确定从哪个物理接口发送数据。此查找使用 OS 路由表。假设您有一个正常的路由表,操作系统将选择具有与目标 IP 相同子网的 ab IP 的接口。因此,如果您向 发送数据10.0.0.2
,您的操作系统将从 发送数据,10.0.0.1
因为它具有相同的子网10.0.0
. 现在操作系统已经选择了一个接口,它仍然不知道将第 3 层 IP 数据包发送到哪个第 2 层 MAC 地址。操作系统不知道这一点的主要原因是 IP 地址可以更改,但第 2 层 MAC 地址不应该更改。无论如何,操作系统都会发出一个 ARP 请求,试图获取 IP 地址的 MAC 地址。如果设备连接正确,操作系统会获取所需 IP 地址的 MAC 地址,并开始向该 MAC 地址发送数据。交换机(智能或哑)确保消息到达所需的 MAC 地址。在接收端,操作系统接收数据包并将数据包中的数据发送到绑定到第 4 层地址(应用程序端口)的套接字。
旁注:技术上可以使用 RAW 套接字将数据仅发送到 MAC 地址,但这是非常技术性的。