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

我最终试图测试一个 UDP 客户端,并希望确保它在不通过环回接口发送数据时工作,以避免由此引入的任何细微问题,例如校验和验证的差异(Bad UDP checksum 无效:为什么?)。


但是,即使将数据发送到不是 的结果socket.gethostbyname(socket.gethostname()),127.0.0.1根据 Wireshark 的说法,数据似乎也是通过环回接口进行的。


以下程序b'somedata'成功发送和接收,并从 Wireshark 捕获以下内容。


import asyncio

import socket


async 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()

http://img.mukewang.com/61e6747500017afa14060567.jpg

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

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


胡说叔叔
浏览 228回答 2
2回答

侃侃无极

要“说服”网络堆栈使用以太网(或 WiFi)卡而不是环回来物理传输帧,请使用广播地址。我已经在我的 Linux 系统上以这种方式成功发送和接收了一个 UDP 数据包。我用tcpdump. 它在以太网接口上显示一个数据包,并且在环回上没有活动。我使用了文字广播地址。套接字模块文档还提到了字符串作为'<broadcast>'特例地址。我没有试过。with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:&nbsp; &nbsp; sock.setblocking(False)&nbsp; &nbsp; sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)&nbsp; &nbsp; sock.connect(('192.168.0.255', 4567))&nbsp; &nbsp; await loop.sock_sendall(sock, b'somedata')&nbsp; &nbsp; await asyncio.sleep(1)笔记:同一网络上的其他主机也会收到 UDP 数据包。确保防火墙/数据包过滤器(例如 Linux iptables/nftables)不会阻止数据包。关于setsockopt:Python socket.error: [Errno 13] Permission denied

潇湘沐

这可能是因为您的主机名指向环回地址,因此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&nbsp;youriptoyourip也可能导致网络驱动程序通过环回接口路由包。另一种方法是在网络路由器之外使用公共 IP。您可以使用此答案中描述的外部服务
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python