繁体   English   中英

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

[英]Send UDP to local server, but not via loopback interface

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

但是,即使将数据发送到socket.gethostbyname(socket.gethostname())的结果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()

在此输入图像描述

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

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

为了“说服”网络堆栈使用以太网(或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]权限被拒绝

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

虽然在这种情况下,从yourip调用yourip可能会导致网络驱动程序通过环回接口路由包。 替代方案是在网络路由器之外使用公共IP。 您可以使用本答案中描述的外部服务

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM