簡體   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