【问题标题】:How to read UDP data from a given port with python in Windows?如何在 Windows 中使用 python 从给定端口读取 UDP 数据?
【发布时间】:2023-01-30 21:08:07
【问题描述】:

在 Windows 10 上,我想从 UDP 端口 9001 读取数据。我创建了以下不提供任何输出的脚本(python 3.10.9):

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("", 9001))
    
while True:
    data, addr = sock.recv(1024)
    print(f"received message: {data.decode()} from {addr}")

我检查了一个设备正在使用端口 9001 发送 UDP 数据线鲨.但是上面的代码只是在 powershell 上“运行”,没有任何输出(也没有任何错误)。

任何想法如何解决这一问题?

我找到了this page电源外壳应该侦听 UDP 端口的脚本。所以我尝试了这个并创建了一个文件Start-UDPServer.ps1,其内容如下所述:

function Start-UDPServer {
    [CmdletBinding()]
    param (
        # Parameter help description
        [Parameter(Mandatory = $false)]
        $Port = 10000
    )
    
    # Create a endpoint that represents the remote host from which the data was sent.
    $RemoteComputer = New-Object System.Net.IPEndPoint([System.Net.IPAddress]::Any, 0)
    Write-Host "Server is waiting for connections - $($UdpObject.Client.LocalEndPoint)"
    Write-Host "Stop with CRTL + C"

    # Loop de Loop
    do {
        # Create a UDP listender on Port $Port
        $UdpObject = New-Object System.Net.Sockets.UdpClient($Port)
        # Return the UDP datagram that was sent by the remote host
        $ReceiveBytes = $UdpObject.Receive([ref]$RemoteComputer)
        # Close UDP connection
        $UdpObject.Close()
        # Convert received UDP datagram from Bytes to String
        $ASCIIEncoding = New-Object System.Text.ASCIIEncoding
        [string]$ReturnString = $ASCIIEncoding.GetString($ReceiveBytes)

        # Output information
        [PSCustomObject]@{
            LocalDateTime = $(Get-Date -UFormat "%Y-%m-%d %T")
            SourceIP      = $RemoteComputer.address.ToString()
            SourcePort    = $RemoteComputer.Port.ToString()
            Payload       = $ReturnString
        }
    } while (1)
}

并开始它电源外壳终端(作为管理员)作为

.\Start-UDPServer.ps1 -Port 9001

它立即返回到 Powershell,没有任何输出(或错误消息)。也许窗户坏了?

如果有最终监听UDP 9001端口的方案,我还是强烈推荐一个Python解决方案!

【问题讨论】:

  • 您是否检查过系统上的防火墙是否阻止了流量?

标签: python windows powershell


【解决方案1】:

据我所知,如果您发布的 Python 代码正在接收任何数据,它应该在运行时给您一个错误,这表明数据根本没有进入流程。

我建议检查该端口的 Windows 防火墙设置,以及您可能正在运行的任何其他基于主机的防火墙。

而且,recv() 方法不返回元组。 recvfrom() 可以,所以下面的代码有效:

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("", 9001))
    
while True:
    data, addr = sock.recvfrom(1024)
    print(f"received message: {data.decode()} from {addr}")

切线说明:Powershell 脚本实际上并不启动 UDP 服务器,它只是创建一个函数来执行此操作。所以如果你想让它真正监听数据报,你需要在最后添加一行Start-UDPServer -Port 9001来调用这个函数。

【讨论】:

    【解决方案2】:

    运行 UDP 服务器并通过类似的 UDP 客户端进行检查的完整代码:

    import socket
    import threading
    import time
    
    _SRV_ADDR = ('127.0.0.1', 9001)
    
    def udp_client_test():
        # Give the server a second to start:
        time.sleep(1)
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.settimeout(1)
        try:
            sock.sendto(b'a request', _SRV_ADDR)
            data, server = sock.recvfrom(1024)
            print(f'client received: «{data.decode()}» from {server}')
        except Exception as e:
            print(f'client exception: {e}')
        sock.close()
    
    if __name__ == '__main__':
        # Run client in another thread:
        threading.Thread(target=udp_client_test).start()
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.bind(_SRV_ADDR)
        try:
            while True:
                data, addr = sock.recvfrom(1024)
                print(f"server received: «{data.decode()}» from {addr}")
                sock.sendto(b'a response', addr)
                # The test is over, let's quit:
                break
        except Exception as e:
            print(f'server exception: {e}')
        sock.close()
    

    在两个不同的 Windows 安装上测试没有问题。
    您也可以将端口更改为 53,注释掉 break 并使用nslookup: nslookup example.com 127.0.0.1

    【讨论】:

      【解决方案3】:

      根据您的脚本,我编写了这段代码。它适用于我的机器

      import socket
      
      UDP_IP = ""
      UDP_PORT = 53
      
      sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
      sock.bind((UDP_IP,UDP_PORT))
      
      while True:
          data, addr = sock.recvfrom(1024)
          print("Received msg: ",data.decode()," from", addr)
      

      如您问题下的评论中所述,如果有任何流量被阻止,请检查主机防火墙。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-12-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多