2016-11-01 25 views
1

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

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) 

我不是蟒蛇亲和无法弄清楚的问题: (

+0

旁白:你的阅读文件的方式只是可怕... –

+0

@ Jean-FrançoisFabreyep ... as i sai d我不是Python代码,我只需要一个快速而脏的UDP套接字来工作:( –

+1

发送给你需要它的IP和端口的人。你绑定到'('localhost',9763)'后来你发送给'('localhost',9763)',所以你发送给自己,而不是其他程序。 – furas

回答

4

对于ST? arters这是搞砸了:

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)呼叫。

+0

非常感谢!你是一个拯救生命的人:D –

0

您需要在您呼叫的目​​的地地址或端口更改为sendto

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

了地址和端口是否Qt应用程序绑定

+0

到同一个端口,9763 –

+0

@SaeidYazdani然后主机必须不同。 2个不同的应用程序不能绑定到同一个“(主机,端口)”对。操作系统不会允许它。 – freakish

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回声客户端是类似的服务器,但不使用绑定()将其套接字连接到的地址。它使用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 

$