2

I've made this sending / receiving scripts but i corrupted file ! i have no idea why I'm getting this issue !

sender.py

#!/usr/bin/env python

from socket import *
import sys

s = socket(AF_INET,SOCK_DGRAM)
host =sys.argv[1]
port = 9999
buf =1024
addr = (host,port)

file_name=sys.argv[2]

f=open(file_name,"rb") 
data = f.read(buf)

s.sendto(file_name,addr)
s.sendto(data,addr)
while (data):
    if(s.sendto(data,addr)):
        print "sending ..."
        data = f.read(buf)
s.close()
f.close()

receiver.py

#!/usr/bin/env python

from socket import *
import sys
import select

host="0.0.0.0"
port = 9999
s = socket(AF_INET,SOCK_DGRAM)
s.bind((host,port))

addr = (host,port)
buf=1024

data,addr = s.recvfrom(buf)
print "Received File:",data.strip()
f = open(data.strip(),'wb')

data,addr = s.recvfrom(buf)
try:
    while(data):
        f.write(data)
        s.settimeout(2)
        data,addr = s.recvfrom(buf)
except timeout:
    f.close()
    s.close()
    print "File Downloaded"

and this the original receiver that I've modify it (works fine 100%)

#!/usr/bin/env python

from socket import *
import sys
import select

host="0.0.0.0"
port = 9999
s = socket(AF_INET,SOCK_DGRAM)
s.bind((host,port))

addr = (host,port)
buf=1024

f = open("file.pdf",'wb')

data,addr = s.recvfrom(buf)
try:
    while(data):
        f.write(data)
        s.settimeout(2)
        data,addr = s.recvfrom(buf)
except timeout:
    f.close()
    s.close()
    print "File Donwloaded"

as you notice it's making file at the beginning.

exacted: client => send file (name.ext) => server:save it (name.ext)

my output : corrupted file for pdf and empty for txt

Hamoudaq
  • 1,490
  • 4
  • 23
  • 42
  • 1
    First off: `except socket.timeout:` is never going to work. You're doing `from socket import *`, so `socket` in your code is actually `socket.socket`. You should be doing `except timeout` or use `import socket` (**highly recommended**). – Thomas Orozco Dec 21 '12 at 16:22
  • i got socket.timeout: timed out ,,,, and when i send pdf file then open it it says it's corrupted file , i have basic knowledge about UDP I've tried my coded that i have provide it in the question ,, thank you – Hamoudaq Dec 21 '12 at 16:22
  • @ThomasOrozco thank you , you've fixed error part , but i've got another problem if i sent an small file it's will not stop (less than 1028) , but when i send big file it works fine , i'am thinking about changing buffer size – Hamoudaq Dec 21 '12 at 16:28

2 Answers2

5

There are two problems here:

Syntax errors:

You're using a from socket import *. It's not an error on its own, but it becomes one when you do except socket.timeout.

Using UDP:

Using UDP, corruption shouldn't be a surprise. You probably don't want to be using UDP here, you should switch to TCP.

Here's why UDP is not appropriate here:

  • Packets may be lost but others could still reach their destination.
  • Packets may be duplicated
  • Packets may arrive in the wrong order

Note that switching to TCP will involve some refactoring of your code (it's a bit more complicated that just replacing SOCK_DGRAM with SOCK_STREAM), but in your case, you have to do it.


I'm not saying UDP is bad, but it's not appropriate in your case.

Andrei
  • 10,918
  • 12
  • 76
  • 110
Thomas Orozco
  • 53,284
  • 11
  • 113
  • 116
  • but i have another script that receive file without being corrupted but the problem with that script it just receive file and named it with random name , i just took it and modify it to receive the name and file from client – Hamoudaq Dec 21 '12 at 16:34
  • @EngHamoud You'll need to provide more information (expected vs actual output) if you need help with this! : ) – Thomas Orozco Dec 21 '12 at 16:38
  • 1
    if I had to guess, I'd say that the reason he has to do a UDP file transfer program like this is because of some **school assignment** to make a UDP file transfer program... because the only reason I can think of to use UDP for file transfers is to explain **how TCP works**... because to make a reliable UDP file transfer program, you will need to handle lost packets, and reassemble the file from packets sent out of order _a la_ bittorrent... and you'll also need some kind of terminator sent at the end to let the receiver know that it's finished. – Cari Dec 10 '13 at 00:23
5

The problem with your code:

  • When data is send through sockets, normally the lower layers will merge the data from multiple sendTo calls and send them together to reduce network load.
  • You are sending the first 1024 bytes of the file twice.

What you should do:

Use some kind of a delimiter string having couple of characters (like "**_$$") so that it won't exist in the actual file binary representation. Then append this delimiter to the end of the filename.

Read from file again before starting the while loop.

At receiver end, receive everything into a single stream and then split using the delimiter. You will have the filename and the file data.

Update:

Working Code (Ubuntu / Windows XP)

# ----- sender.py ------

#!/usr/bin/env python

from socket import *
import sys

s = socket(AF_INET,SOCK_DGRAM)
host =sys.argv[1]
port = 9999
buf =1024
addr = (host,port)

file_name=sys.argv[2]

s.sendto(file_name,addr)

f=open(file_name,"rb")
data = f.read(buf)
while (data):
    if(s.sendto(data,addr)):
        print "sending ..."
        data = f.read(buf)
s.close()
f.close()

# ----- receiver.py -----

#!/usr/bin/env python

from socket import *
import sys
import select

host="0.0.0.0"
port = 9999
s = socket(AF_INET,SOCK_DGRAM)
s.bind((host,port))

addr = (host,port)
buf=1024

data,addr = s.recvfrom(buf)
print "Received File:",data.strip()
f = open(data.strip(),'wb')

data,addr = s.recvfrom(buf)
try:
    while(data):
        f.write(data)
        s.settimeout(2)
        data,addr = s.recvfrom(buf)
except timeout:
    f.close()
    s.close()
    print "File Downloaded"

Usage

>> python recevier.py

>> python sender.py localhost filename.txt
ATOzTOA
  • 34,814
  • 22
  • 96
  • 117
  • f.write(str[1]) IndexError: list index out of range – Hamoudaq Dec 21 '12 at 18:32
  • The error means, the delimiter is not in the received data. Try sending a text file and printing out the whole data received... – ATOzTOA Dec 21 '12 at 18:40
  • tried with pdf and got TypeError: file() argument 1 must be encoded string without NULL bytes, not str tried with txt and got IndexError: list index out of range – Hamoudaq Dec 21 '12 at 18:44
  • windows , i think there's nothing to do with os – Hamoudaq Dec 21 '12 at 20:10
  • got the same error ! i believe the problem is with receiver not sender – Hamoudaq Dec 21 '12 at 20:23
  • 1
    It works fine in Ubuntu with Python 2.6. Please update your question with the latest code you are trying with and the error message including line numbers. – ATOzTOA Dec 22 '12 at 05:06
  • But if the file is too large (i'm using a png of 22kb) the content is truncated randomly on the receiver side (testing on remote machine). I think it's nothing to do with the code, but the use of UDP. – Parmaia Nov 19 '13 at 17:35
  • @Parmaia We have been using this for larger files (1M+) and faced no issues. – ATOzTOA Nov 20 '13 at 05:36