Pelonomi Moiloa
Pelonomi Moiloa

Reputation: 582

How to send end of file without closing tcp socket

I am trying to send a file over a tcp socket in a peer to peer chat system coded in python. The receiving socket seems not to know that there is no more file to receive. The only way I can get the receiving socket to not anticipate the data that isn't coming is by closing the sending socket (using socket.shutdown(socket.SHUT_WR)). However, closing the sending socket is not an option because I need that socket to send other messages. I fisrt tried allocating a new port for file sending/receiving and failed. Now, I have tried creating an end of file "signal" but it does not get recognized on the receiving end as a message separate from the tcp segment, so I am stuck.

The sending code looks like this:

def sendFile(self,filePath):
    try:
        f = open(filePath, 'rb')
        print 'file opened'
        for soc in self.allClients.keys():
            try:
                f = open(filePath, 'rb')
            except:
                print "File does not exist"
            print 'Sending File: ' + filePath
            l = f.read(1024)
            while (l):
                print 'Sending...'
                soc.send(l)
                l = f.read(1024)
            soc.send('end')
            f.close()
            print 'File sent'                
    except:
        print "File does not exist"

the receiving code looks like this:

 def receiveFile(self, ext, clientsoc):   
    f = open('receivedFile' + ext,'wb')

    print "Receiving File..."
    l = clientsoc.recv(1024)
    while(l):
        print "Receiving..."
        if (l is not 'end'):
            f.write(l)   
            print l + '\n'
            l = clientsoc.recv(1024)
        else:
            break
    f.close()
    print "Received Fileeeeeooooo"

Even more strange, this code works when I am using it outside of my peer programme. Any help would be greatly appreciated, I have been struggling with this for two days now.

Upvotes: 3

Views: 6931

Answers (3)

Akrem
Akrem

Reputation: 71

Your receiving code works but still there is a problem you need to fix real quick. If your filesize is under 1024, your socket will keep listening for ever and in order to fix this problem you need to change your code like below.

def receiveFile(self,ext, filesize, clientsoc):   
    total = 0
    f = open('receivedFile' + ext,'wb')
    print("Receiving File...")
    l = clientsoc.recv(1024)
    total = len(l)
    while(l):
        print("Receiving...")
        f.write(l) 
        if (str(total) != filesize):
            print 'trying to receive'
            l = clientsoc.recv(1024)
            total = total + len(l)
        if(int(total)>= int(filesize)):
            break
    f.close()
    print("Received Fileeeeeoooo")

Upvotes: 0

Pelonomi Moiloa
Pelonomi Moiloa

Reputation: 582

Sending the file size first worked!!

New code looks like this.

Sending code:

def sendFileOrImage(self,path):

    name, ext = os.path.splitext(path)
    filesize = str(os.path.getsize(path))
    message = filesize + ',' + ext
    print 'message'
    for client in self.allClients.keys():
        client.send(message)
        self.sendFile(path)

def sendFile(self,filePath):
    try:
        f = open(filePath, 'rb')
    except:
        print "File does not exist"
    print 'Sending File: ' + filePathty
    for soc in self.allClients.keys():
        l = f.read(1024)
        while (l):
            print 'Sending...'
            soc.send(l)
            l = f.read(1024)
        f.close()
        print 'File sent'

Receiving code:

def receiveFile(self,ext, filesize, clientsoc):   
    total = 0
    f = open('receivedFile' + ext,'wb')

    print "Receiving File..."
    l = clientsoc.recv(1024)
    total = len(l)
    while(l):
        print "Receiving..."

        f.write(l) 
        if (str(total) != filesize):
            print 'trying to receive'
            l = clientsoc.recv(1024)
            total = total + len(l)
        else:
            break
    f.close()
    print "Received Fileeeeeooooo"

Thanks everyone for the help!

Upvotes: 2

Daniel
Daniel

Reputation: 42748

First of all, you must not compare strings with is or is not:

>>> a = "he"
>>> a + "llo" is "hello"
False

Second, TCP is a streaming protocol. recv is getting up to 1024 bytes, but could be less, and if you send two pieces from your server, they can be merged into one recv. So l is not likely to be "end" but "last bytes of the file's end". And if you check for "end", "end" is not allowed to be in the file. Best solution is to send the length of the file first, and then send and recv length bytes.

PS: you probably want to use sendall at the server side.

Upvotes: 3

Related Questions