Python发送UDP数据包

69

我正在尝试编写一个程序来发送UDP数据包,就像https://wiki.python.org/moin/UdpCommunication中看到的那样。该代码似乎是使用Python 2编写的:

import socket

UDP_IP = "127.0.0.1"
UDP_PORT = 5005
MESSAGE = "Hello, World!"

print "UDP target IP:", UDP_IP
print "UDP target port:", UDP_PORT
print "message:", MESSAGE

sock = socket.socket(socket.AF_INET, # Internet
             socket.SOCK_DGRAM) # UDP
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))

如果我在要打印的内容周围加上圆括号,它会在屏幕上打印出来。

我需要做什么才能使其生效?


1
你是否正在运行接收UDP数据包的示例代码?除非你有东西来接收数据包,否则它似乎不会做任何事情(除了在控制台上打印)。 - circuitBurn
1
你在Wireshark中看到网络流量了吗? - RickyA
5个回答

91

在Python3x中,你需要将字符串转换为原始字节。你需要将字符串编码为字节。在网络上传输时,你需要发送字节而不是字符。你说得对,在Python 2x中这会起作用,因为在Python 2x中,套接字上的socket.sendto使用“纯”字符串而不是字节。尝试这个:

print("UDP target IP:", UDP_IP)
print("UDP target port:", UDP_PORT)
print("message:", MESSAGE)

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
sock.sendto(bytes(MESSAGE, "utf-8"), (UDP_IP, UDP_PORT))

1
谢谢!我在 Wireshark 上检查了一下,它成功地发送了一个 UDP 数据包。+1 接受的答案。 - user2059619
1
这仅适用于文本消息。请记住,您可以使用这些函数在网络上传输和接收任意数据,因此您不能总是假定解码/编码为utf8是有意义的。 - user2957811

10

你的代码对我来说可以直接使用。 我正在使用Linux上的netcat进行验证。

使用netcat,我可以执行nc -ul 127.0.0.1 5005,这将在以下位置侦听数据包:

  • IP: 127.0.0.1
  • 端口号: 5005
  • 协议: UDP

话虽如此,当我运行你的脚本时,同时也运行了netcat,下面是我看到的输出:

[9:34am][wlynch@watermelon ~] nc -ul 127.0.0.1 5005
Hello, World!

4

Manoj的回答是正确的,另一种选项是使用MESSAGE.encode()或encode('utf-8')将其转换为字节。bytes和encode基本相同,encode与Python 2兼容。有关更多信息,请参见这里

完整代码:

import socket

UDP_IP = "127.0.0.1"
UDP_PORT = 5005
MESSAGE = "Hello, World!"

print("UDP target IP: %s" % UDP_IP)
print("UDP target port: %s" % UDP_PORT)
print("message: %s" % MESSAGE)

sock = socket.socket(socket.AF_INET, # Internet
                     socket.SOCK_DGRAM) # UDP
sock.sendto(MESSAGE.encode(), (UDP_IP, UDP_PORT))

2

如果您正在运行Python 3,则需要将print语句更改为print函数,即在print语句后面加上括号()。

上述内容唯一的作用是打印输出,除非您有侦听 127.0.0.1端口5005 的程序,因为您正在发送数据包而不是接收它 - 所以您需要在另一个控制台窗口中实现并启动示例的另一部分,使其等待消息。


0
这是一个完整的示例,已经在CentOS 7上使用Python 2.7.5测试过。
#!/usr/bin/python

import sys, socket

def main(args):
    ip = args[1]
    port = int(args[2])
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    file = 'sample.csv'

    fp = open(file, 'r')
    for line in fp:
        sock.sendto(line.encode('utf-8'), (ip, port))
    fp.close()

main(sys.argv)

该程序从当前目录读取一个名为sample.csv的文件,并将每一行发送到单独的UDP数据包中。如果该程序保存在名为send-udp的文件中,则可以通过执行类似以下命令来运行它:
$ python send-udp 192.168.1.2 30088

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接