2016-11-01 19 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 

$