1

我需要模拟一个 UDP 服务器,它在无限循环中逐行发送文本文件的内容。我已经编写了下面的代码,但在另一端我没有收到任何东西(另一端是 Qt 代码,我确信它可以工作):

import socket
import time

# setup UDP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sa = ('localhost', 9763)
sock.bind(sa)

filename = '/home/saeid/Documents/data.txt'  # file to read
numlines = sum(1 for line in open(filename))  # get number of lines in file


# get line of a file
def get_line(line):
    with open(filename) as fp:
        for i, l in enumerate(fp):
            if i == line:
                return l

# main loop
while True:
    currline = 0
    while currline < numlines:
        sock.sendto(get_line(currline), sa)
        currline += 1
        time.sleep(1)

我不是 python 专业人士,无法解决问题:(

4

3 回答 3

4

对于初学者来说,这是一团糟:

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sa = ('localhost', 9763)
sock.bind(sa)
...
sock.sendto(get_line(currline), sa)

通过绑定,您基本上说“我想在该主机/端口上收听”。但是随后您将数据发送到同一主机/端口。我假设还有其他一些目标地址,例如sock.sendto(get_line(currline), ('my_host', 1234)). 顺便说一句,你为什么要绑定到地址呢?sock.bind(sa)线是不必要的,删除它。


另一件事是您的文件读取代码效率极低且难以阅读(我花了一段时间才理解发生了什么)。尝试这样的事情:

with open(filename, 'r') as fo:
    while True:
        for line in fo:
            sock.sendto(line, DEST_ADDRESS)
            time.sleep(1)
        fo.seek(0)  # go back to the begining of the file and repeat

并摆脱get_line功能。

这至少是我在阅读您的描述后得出的结论。如果您不想无限发送相同的文件,那么您可以摆脱while True:循环并fo.seek(0)调用。

于 2016-11-01T17:46:45.817 回答
1

谷歌大叔想出了用户数据报客户端和服务器

用户数据报客户端和服务器

用户数据报协议 (UDP) 的工作方式与 TCP/IP 不同。TCP 是面向流的协议,确保所有数据都以正确的顺序传输,而 UDP 是面向消息的协议。UDP 不需要长连接,因此设置 UDP 套接字要简单一些。另一方面,UDP 消息必须适合单个数据包(对于 IPv4,这意味着它们只能容纳 65,507 字节,因为 65,535 字节的数据包还包含标头信息),并且无法像 TCP 那样保证传送。

回声服务器

由于没有连接,服务器本身不需要监听和接受连接。它只需要使用 bind() 将其套接字与端口相关联,然后等待各个消息。

import socket
import sys

# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# Bind the socket to the port
server_address = ('localhost', 10000)
print >>sys.stderr, 'starting up on %s port %s' % server_address
sock.bind(server_address)

使用 recvfrom() 从套接字读取消息,它返回数据以及发送数据的客户端地址。

while True:
    print >>sys.stderr, '\nwaiting to receive message'
    data, address = sock.recvfrom(4096)

    print >>sys.stderr, 'received %s bytes from %s' % (len(data), address)
    print >>sys.stderr, data

    if data:
        sent = sock.sendto(data, address)
        print >>sys.stderr, 'sent %s bytes back to %s' % (sent, address)

回声客户端

UDP 回显客户端类似于服务器,但不使用 bind() 将其套接字附加到地址。它使用 sendto() 将其消息直接传递到服务器,并使用 recvfrom() 接收响应。

import socket
import sys

# Create a UDP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

server_address = ('localhost', 10000)
message = 'This is the message.  It will be repeated.'

try:

    # Send data
    print >>sys.stderr, 'sending "%s"' % message
    sent = sock.sendto(message, server_address)

    # Receive response
    print >>sys.stderr, 'waiting to receive'
    data, server = sock.recvfrom(4096)
    print >>sys.stderr, 'received "%s"' % data

finally:
    print >>sys.stderr, 'closing socket'
    sock.close()

客户端和服务器一起

运行服务器会产生:

$ python ./socket_echo_server_dgram.py

starting up on localhost port 10000

waiting to receive message
received 42 bytes from ('127.0.0.1', 50139)
This is the message.  It will be repeated.
sent 42 bytes back to ('127.0.0.1', 50139)

waiting to receive message

客户端输出是:

$ python ./socket_echo_client_dgram.py

sending "This is the message.  It will be repeated."
waiting to receive
received "This is the message.  It will be repeated."
closing socket

$
于 2016-11-01T17:54:37.883 回答
0

您需要将呼叫中的目标地址或端口更改为sendto

        peer_address = ('localhost', peer_port)
        sock.sendto(get_line(currline), peer_address)

Qt 应用程序绑定到哪个地址和端口?

于 2016-11-01T17:46:14.407 回答