Search code examples
pythonsocketstcp

Transferring File over TCP using Python


I am new to python and finding it really difficult trying to understand how to send files using sockets with a tcp connection i found this code in another question that seems to be useful

Client Side

def _sendFile(self, path):
    sendfile = open(path, 'rb')
    data = sendfile.read()

    self._con.sendall(encode_length(len(data))) # Send the length as a fixed size message
    self._con.sendall(data)


    # Get Acknowledgement
    self._con.recv(1) # Just 1 byte

Server Side

def _recieveFile(self, path):
    LENGTH_SIZE = 4 # length is a 4 byte int.
    # Recieve the file from the client
    writefile = open(path, 'wb')
    length = decode_length(self.con.read(LENGTH_SIZE) # Read a fixed length integer, 2 or 4 bytes
    while (length):
        rec = self.con.recv(min(1024, length))
        writefile.write(rec)
        length -= sizeof(rec)

    self.con.send(b'A') # single character A to prevent issues with buffering

Now i have two problems with this code First

self._con.sendall(encode_length(len(data)))

in this line it gives me an error saying encode_length is undefined

Secondly these are functions that send and receive file Where do i call them Do i first form a TCP Connection and then call these functions And how exactly to call them , if i call them directly it gives me an error on client side saying _sendFile(self, path) takes two arguments (since i am not passing self just the path)

Thirdly i am using function from os library to get complete path , So i am calling the function like

_sendFile(os.path.abspath("file_1.txt"))

is this the correct way to pass the argument

Sorry i know this question is pretty basic and lame but everywhere online i can basically get the function but not how to call it

right now this is how i am calling the function

serverIP = '192.168.0.102'
serverPort = 21000

clientSocket = socket(AF_INET, SOCK_STREAM)

message = "Want to Backup a Directory"


clientSocket.connect((serverIP, serverPort))

_sendFile(os.path.abspath("file_1.txt"))

Which is basically wrong

I am using the same computer for both Client and Server

Running Python on Ubuntu using terminal


Solution

  • First problem:

    It's because you simply haven't defined functions encode/decode_lenght.


    Second problem:

    Your function is: def _sendFile(self, path): ....
    Do you know how to use self? It is used in the classes. So define it without self, or use classes:

    Example:

    from socket import *
    class Client(object):
    
        def __init__(self):
    
            self.clientSocket = socket(AF_INET, SOCK_STREAM)
    
        def connect(self, addr):
    
            self.clientSocket.connect(addr)
    
        def _sendFile(self, path):
    
            sendfile = open(path, 'rb')
            data = sendfile.read()
    
            self._con.sendall(encode_length(len(data))) # Send the length as a fixed size message
            self._con.sendall(data)
    
    
            # Get Acknowledgement
            self._con.recv(1) # Just 1 byte
    
    >>> client = Client()
    >>> client.connect(("192.168.0.102", 21000))
    >>> client._sendFile(os.path.abspath("file_1.txt")) # If this file is in your current directory, you may just use "file_1.txt"
    

    And same (almost) for Server.


    Where to define these functions? In the code ofcorse! What should your functions do?
    OK, an example:

    def encode_length(l):
    
        #Make it 4 bytes long
        l = str(l)
        while len(l) < 4:
            l = "0"+l 
        return l
    
    # Example of using
    >>> encode_length(4)
    '0004'
    >>> encode_length(44)
    '0044'
    >>> encode_length(444)
    '0444'
    >>> encode_length(4444)
    '4444'
    

    About self:

    Just a little bit:

    self redirects to your current object, ex:

    class someclass:
        def __init__(self):
            self.var = 10
        def get(self):
            return self.var
    
    >>> c = someclass()
    >>> c.get()
    10
    >>> c.var = 20
    >>> c.get()
    20
    >>> someclass.get(c)
    20
    >>>
    

    How does someclass.get(c) work? While executing someclass.get(c), we are not creating an new instance of someclass. When we call .get() from an someclass instance, it automaticly sets self to our instance object. So someclass.get(c) == c.get() And if we try to do someclass.get(), self was not defined, so it will raise an error: TypeError: unbound method get() must be called with someclass instance as first argument (got nothing instead)


    You can use decorator to call functions of a class (not its instance!):

    class someclass:
        def __init__(self):
            self.var = 10
        def get(self):
            return 10 # Raises an error
        @classmethod
        def get2(self):
            return 10 # Returns 10!
    

    Sorry for my bad explanations, my English is not perfect


    Here are some links:

    server.py

    client.py