在原始套接字上接收 UDP 数据报?

Receive UDP datagram on raw socket?

出于教育目的,我正在尝试使用原始套接字在 ruby 中编写自己的 UDP 实现。

这是我目前的情况:

require 'socket'

addr = Socket.pack_sockaddr_in(4567, '127.0.0.1')

socket = Socket.new(
  Socket::PF_INET,
  Socket::SOCK_RAW,
  Socket::IPPROTO_RAW
)

socket.bind(addr)
socket.recvfrom(1024)

我是这样测试的:

require 'socket'

udp = UDPSocket.new
udp.send "Hello World", 0, "127.0.0.1", 4567

但是对 recvfrom 的调用无限期阻塞。

如果我改成这样:

socket = Socket.new(
  Socket::PF_INET,
  Socket::SOCK_DGRAM,
  Socket::IPPROTO_UDP
)

它当然有效,因为这是接受 UDP 数据包的系统级方式。

如何在原始套接字上接收 UDP 数据包?
明确一点:我想自己处理实际的 UDP 协议(​​解码数据报并执行校验和)!

原始套接字在 IP 级别工作。您不能将原始套接字绑定到端口。您可以使用 bind 绑定到本地地址,或者通过设置正确的套接字选项绑定到接口(我不知道如何在 Ruby 中做到这一点,在 C 中您调用 setsockopt。而不是 IPPROTO_RAW 你应该在 protocol.You 中使用 IPPROTO_UDP 将接收在该 IP 地址或该接口上接收到的所有 UDP 数据报(如果套接字绑定到它)。