将UDP发送到本地服务器,但不通过回送接口

时间:2019-04-22 08:36:52

标签: python python-3.x sockets udp python-asyncio

我最终将尝试测试UDP客户端,并希望确保在通过回送接口发送数据 not 时它可以正常工作,以避免由此引起的任何细微问题,例如校验和验证(Bad UDP checksum has no effect: why?)。

但是,即使将数据发送到不是socket.gethostbyname(socket.gethostname())的{​​{1}}的结果,那么根据Wireshark的说法,数据似乎仍通过回送接口传输。

下面的程序成功发送和接收127.0.0.1,并从Wireshark中捕获了以下内容。

b'somedata'

enter image description here

如何将数据从本地运行的客户端发送到本地运行的服务器,但是要避免使用环回接口,而是将数据实际发送到网络中?

理想情况下,答案适用于Linux和macOS。

2 个答案:

答案 0 :(得分:1)

要“说服”网络堆栈使用以太网(或WiFi)卡而不是环回来物理传输帧,请使用广播地址。

我已经在Linux系统上成功发送和接收了UDP数据包。我用tcpdump进行了验证。它显示了以太网接口上的一个数据包,而环回时没有任何活动。

我使用了原义广播地址。 socket module文档还提到了字符串'<broadcast>'作为特例地址。我没有尝试过。

with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
    sock.setblocking(False)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    sock.connect(('192.168.0.255', 4567))
    await loop.sock_sendall(sock, b'somedata')
    await asyncio.sleep(1)

注意:

  1. 同一网络上的其他主机也将接收UDP数据包。
  2. 确保防火墙/数据包过滤器(例如Linux iptables / nftables)不会阻止数据包。
  3. 关于setsockoptPython socket.error: [Errno 13] Permission denied

答案 1 :(得分:0)

这可能是因为您的主机名指向回送地址,因此socket.gethostbyname(socket.gethostname())将产生127.0.0.1

您需要做的是取消从主机名指向回送地址的指示:

  • 在Linux中,编辑/etc/hosts并注释掉行127.0.0.1 YOUR_HOSTNAME
  • 在Windows中,您应该拥有c:\windows\system32\drivers\etc\hosts,它看起来与Linux类似

此后,如果您呼叫socket.gethostbyname(socket.gethostname()),它将产生DHCP分配的IP。

尽管即使在这种情况下,从youripyourip的调用也可能导致网络驱动程序通过环回接口路由程序包。替代方法是在网络路由器外部使用公共IP。您可以按照this answer

中的说明使用外部服务