Python UDP Server发送文本文件的行

时间:2016-11-01 17:33:37

标签: python python-2.7 python-sockets

我需要模拟一个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 pro并且无法弄清楚问题:(

3 个答案:

答案 0 :(得分: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)调用。

答案 1 :(得分:1)

叔叔谷歌提出了User Datagram Client and Server

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

用户数据报协议(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 echo客户端与服务器类似,但不使用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

$

答案 2 :(得分:0)

您需要将通话中的目的地地址或端口更改为sendto

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

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