为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

胡说叔叔 2022-01-18 16:03:44
我最终试图测试一个 UDP 客户端,并希望确保它在不通过环回接口发送数据时工作,以避免由此引入的任何细微问题,例如校验和验证的差异(Bad UDP checksum 无效:为什么?)。但是,即使将数据发送到不是 的结果socket.gethostbyname(socket.gethostname()),127.0.0.1根据 Wireshark 的说法,数据似乎也是通过环回接口进行的。以下程序b'somedata'成功发送和接收,并从 Wireshark 捕获以下内容。import asyncioimport socketasync def server():    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:        sock.setblocking(False)        sock.bind(('', 4567))        data = await loop.sock_recv(sock, 512)        print('Received', data)async def main():    local_ip = socket.gethostbyname(socket.gethostname())    print('Local IP', local_ip)  # Outputs 192.168.0.34    asyncio.ensure_future(server())    await asyncio.sleep(0)    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:        sock.setblocking(False)        sock.connect((local_ip, 4567))        await loop.sock_sendall(sock, b'somedata')        await asyncio.sleep(1)loop = asyncio.get_event_loop()loop.run_until_complete(main())loop.close()如何将数据从本地运行的客户端发送到本地运行的服务器,但避免环回接口并实际将数据发送到网络?理想情况下,答案将适用于 Linux 和 macOS。
查看完整描述

2 回答

?
侃侃无极

TA贡献2051条经验 获得超10个赞

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


我已经在我的 Linux 系统上以这种方式成功发送和接收了一个 UDP 数据包。我用tcpdump. 它在以太网接口上显示一个数据包,并且在环回上没有活动。


我使用了文字广播地址。套接字模块文档还提到了字符串作为'<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


查看完整回答
反对 回复 2022-01-18
?
潇湘沐

TA贡献1816条经验 获得超6个赞

这可能是因为您的主机名指向环回地址,因此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。

即使在这种情况下,调用 from youriptoyourip也可能导致网络驱动程序通过环回接口路由包。另一种方法是在网络路由器之外使用公共 IP。您可以使用此答案中描述的外部服务


查看完整回答
反对 回复 2022-01-18
  • 2 回答
  • 0 关注
  • 227 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信