views:

90

answers:

6

Hi all, I write a little program that sends file from client to server trough udp socket connection.. the program works correctly but if the file I transfer is larger than 8192 kb the stream stops and the file I receive is corrupt.. How can I avoid this limitation?

server.py

host = ...
port = ...
filename = ...

buf = 2048
addr = (host, port)

UDPSock = socket(AF_INET, SOCK_DGRAM)
UDPSock.bind(addr)

f = open(filename, 'wb')

block,addr = UDPSock.recvfrom(buf)
while block:
    if(block == "!END"): # I put "!END" to interrupt the listener
        break
    f.write(block)
    block,addr = UDPSock.recvfrom(buf)

f.close()
UDPSock.close()

client.py

host = ...
port = ...
filename = ...

buf = 2048
addr = (host, port)

UDPSock = socket(AF_INET, SOCK_DGRAM)

f = open(filename, 'rb')

block = f.read(buf)
while block:
        UDPSock.sendto(block, addr)
        block = f.read(buf)

UDPSock.sendto("!END", addr)
f.close()
UDPSock.close()
+2  A: 

You have to split the file into smaller chunks before sending t. 8192 is quite big and I think you could get in trouble when sending this over the Internet, I would stick to 512 bytes instead. Also remember that UDP is not a reliable protocol, i.e. some of your packets might not come at all. I suggest using TCP for transferring files, it solves all the trouble you will have to solve yourself when using UDP.

dark_charlie
thanks, I need to use UDP.. How can I chunk the file? In my example I read 2kb and I send this packet.. It's not the way to make packets? I need to open a connection for every packet?
frx08
No, you don't need to open a new connection for each packet. The way you use it in your updated example should work considering you are 100% sure that !END won't appear in the data you are sending.
dark_charlie
+1  A: 

it would probably be a good idea to use tcp for large file transfers.

What you would need to do with udp is split the file up into chunks, hanle lost chunks, retrying and out of order pkts.

With tcp you dont.

MarkR
thanks, I need to use UDP.. How can I chunk the file? In my example I read 2kb and I send this packet.. It's not the way to make packets? I need to open a connection for every packet?
frx08
If you want to use UDP, then you are wasting a lot of effort. You effectively need to duplicate what TCP does. In order to achieve decent transfer rates on a high latency link, you need to send more data before the previous stuff has been acknowledged, and remember what's been ack'd and what hasn't. You need to tolerate lost packets and packets out of order. You need to put decent checksums on packets (IP checksum is too weak to avoid corruption when transferring big / important data) and all sorts of other things.
MarkR
+1  A: 

The 8192 limit you hit corresponds to the size of socket send & receive buffers in Windows. I'm surprised it works at all for files above 1460 bytes, as the packets would have been truncated to that or smaller before they were put onto the wire. Were you testing within the same host?

When you've figured that out, you will then have to deal with packets ariving out of order,, more than once, or not at all. Are you sure you have to use UDP? It's not for the uninitiated.

EJP
I'm using UDP because it's for testing purpose only.. I solve my problem putting a sleep time between the different packets in the order of .0001 secs.. I'm not worried about loosing packets because I send media files so I can tolerate packet loosing and I don't need a great quality.. for a file of 4mb I send 2000 packets and I receive 1996 packets between two different hosts with a speed of 1000 kb/s with an optimal quality of the file
frx08
+1  A: 

All you are doing is very poorly re-implementing TCP, the only reason to use UDP should be for 1-to-many transfers or a constantly running enterprise service bus middleware.

Using UDP as an unreliable uni-directional transport should be considered a very small niche solution after exhausting the existing well defined transports.

Note for large data transfers over an internet, lower case 'I', are still only reliable and you should usually add application framing and payload verification.

I would recommend investigating existing file transfer technologies such as FSP (UDP), HTTP (TCP), SPDY (optimised HTTP), or for integration with other communications rolling your own above an existing message-orientated-middleware system such as JBoss or 0MQ.

Steve-o
+1  A: 

You still haven't explained why you must use UDP - it simply isn't designed for high volume data transfers as it doesn't have any (simple) congestion management.

If you are sending VoIP then when not simply transmit at real-time, not "as fast as possible"?

FWIW, typical VoIP systems packetise the data into 20ms chunks or thereabouts. Hence if you're using an voice codec like GSM which requires 13 kbps, you only need to chunk into 260 bits (~32 bytes) per packet, and send them every 0.02 seconds.

Alnitak
thanks.. those are the informations I'm looking for.. I was convinced that UDP is the only way to have a real-time data transfer.. so I can use a TCP connection without having problems with real-time transfers
frx08
No, you _should_ use UDP if what you want is real-time transfer of VoIP data at normal audio rates. See in particular the RTP protocol, which is what real VoIP systems use and runs over UDP. What you shouldn't do is use UDP for bulk transfer "as quickly as possible".
Alnitak
+1  A: 

If you have to use UDP, look at http://en.wikipedia.org/wiki/Trivial_File_Transfer_Protocol

It defines a reliable protocol. If your context allows TCP you should prefer to use that.

harper