pythonnetwork-programmingtcpfileserver

Downloading a file using TCP(Client/Server)?


I am trying to make a TCP (Client and Server) in python to download a file that is available on the Server. I am a total beginner in networking in Python, and following a tutorial for this purpose. The problem I am getting is that whenever I try to download a file from the server I get this error:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python3.4/threading.py", line 920, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.4/threading.py", line 868, in run
    self._target(*self._args, **self._kwargs)
  File "fileServer.py", line 8, in RetrFile
    sock.send("EXISTS " + str(os.path.getsize(filename)));
TypeError: 'str' does not support the buffer interface

FileServer.py

import socket;
import threading;
import os;

def RetrFile(name,sock):
    filename = sock.recv(1024).decode();
    if os.path.isfile(filename):
        sock.send("EXISTS " + str(os.path.getsize(filename)));
        userResponse = sock.recv(1024).decode();
        if (userResponse[:2] == 'OK'):
            with open(filename,'rb') as f:
                bytesToSend = f.read(1024);
                sock.send(bytesToSend);
                while (bytesToSend != ""):
                    byteToSend = f.read(1024);
                    sock.send(bytesToSend);
    else:
        sock.send("ERR");
    sock.close();

def Main():
    host = "127.0.0.1";
    port = 5003;

    s = socket.socket();
    s.bind((host,port));

    s.listen(5);

    print("Server Started.")

    while True:
        c , addr = s.accept();
        print("Client connected ip : " + str(addr));
        t = threading.Thread(target = RetrFile,args=("retrThread",c))
        t.start();
    s.close();

if __name__ == '__main__':
    Main();

FileClient.py

import socket

def Main():
    host = "127.0.0.1";
    port = 5003;

    s = socket.socket();
    s.connect((host,port));

    filename = input("Filename? -> ");
    if (filename != "q"):
        s.send(filename.encode())
        data = s.recv(1024)
        if (data[:6] == "EXISTS"):
            filesize = long(data[6:])
            message = input("File Exists, " + str(fielsize) + "Bytes, download? (Y/N)? -> ");
            if (message == "Y"):
                s.send("OK")
                f = open('new_'+filename,'wb')
                data = s.recv(1024)
                totalRecv = len(data)
                f.write(data)
                while(totalRecv < filesize):
                    data = s.recv(1024);
                    totalRecv += len(data)
                    f.write(data)
                    print("{0:.2f}".format((totalRecv/float(filesize))*100 + "%Done"));
                print("Download Complete!");

        else:
            print("File does not exist!");
    s.close();

if __name__ == '__main__':
    Main();

Solution

  • You need to be sending bytes to the socket, not a string. You can convert a string to a bytes with .encode() Try:

    message = "EXISTS " + str(os.path.getsize(filename))
    sock.send(message.encode())
    

    As a side note, you don't need semicolons when using Python, so I would recommend removing them from your code.