Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need to transfer multiple files from client to server

I'm recently working on a project in which I'm basically making a dropbox clone. The server and client are working fine but I'm having a slight issue. I'm able to transfer a single file from the client to the server but when I try to transfer all the files together it gives me an error after the transfer of the first file so basically my code is only working for a single file. I need to make it work for multiple files. Any help will be appreciated. Here's my code

Server Code

import socket
import thread
import hashlib

serversock = socket.socket()
host = socket.gethostname();
port = 9000;
serversock.bind((host,port));
filename = ""
serversock.listen(10);
print "Waiting for a connection....."

clientsocket,addr = serversock.accept() 
print("Got a connection from %s" % str(addr))
while True:
    size = clientsocket.recv(1)
    filesz = clientsocket.recv(1)
    if filesz.isdigit():
        size += filesz
        filesize = int(size)
    else:
        filesize = int(size)    
    print filesize
    for i in range(0,filesize):
        if filesz.isdigit():
            filename += clientsocket.recv(1)
        else:
            filename += filesz
            filesz = "0"
    print filename      
    file_to_write = open(filename, 'wb')
    while True:
        data = clientsocket.recv(1024)
        #print data
        if not data:
            break
        file_to_write.write(data)
    file_to_write.close()
    print 'File received successfully'
serversock.close()

Client Code

import socket
import os
import thread

s = socket.socket() 
host = socket.gethostname()                           
port = 9000
s.connect((host, port))
path = "C:\Users\Fahad\Desktop"
directory = os.listdir(path)
for files in directory:
    print files  
    filename = files
    size = bytes(len(filename))
    #print size
    s.send(size)
    s.send(filename)
    file_to_send = open(filename, 'rb')
    l = file_to_send.read()
    s.sendall(l)
    file_to_send.close()       
    print 'File Sent'                                              
s.close()                                                                           

Here's the error that I get

Waiting for a connection.....
Got a connection from ('192.168.0.100', 58339)
13
Betternet.lnk
File received successfully
Traceback (most recent call last):
  File "server.py", line 22, in <module>
    filesize = int(size)
ValueError: invalid literal for int() with base 10: ''
like image 531
Fahad Cheema Avatar asked Feb 06 '16 20:02

Fahad Cheema


1 Answers

There are several minor issues in your snippet. Maybe you could do something like this?

import socket
import thread
import hashlib

serversock = socket.socket()
host = socket.gethostname();
port = 9000;
serversock.bind((host,port));
filename = ""
serversock.listen(10);
print "Waiting for a connection....."

clientsocket,addr = serversock.accept()
print("Got a connection from %s" % str(addr))
while True:
    size = clientsocket.recv(16) # Note that you limit your filename length to 255 bytes.
    if not size:
        break
    size = int(size, 2)
    filename = clientsocket.recv(size)
    filesize = clientsocket.recv(32)
    filesize = int(filesize, 2)
    file_to_write = open(filename, 'wb')
    chunksize = 4096
    while filesize > 0:
        if filesize < chunksize:
            chunksize = filesize
        data = clientsocket.recv(chunksize)
        file_to_write.write(data)
        filesize -= len(data)

    file_to_write.close()
    print 'File received successfully'
serversock.close()

Client:

import socket
import os
import thread

s = socket.socket()
host = socket.gethostname()
port = 9000
s.connect((host, port))
path = "blah"
directory = os.listdir(path)
for files in directory:
    print files
    filename = files
    size = len(filename)
    size = bin(size)[2:].zfill(16) # encode filename size as 16 bit binary
    s.send(size)
    s.send(filename)

    filename = os.path.join(path,filename)
    filesize = os.path.getsize(filename)
    filesize = bin(filesize)[2:].zfill(32) # encode filesize as 32 bit binary
    s.send(filesize)

    file_to_send = open(filename, 'rb')

    l = file_to_send.read()
    s.sendall(l)
    file_to_send.close()
    print 'File Sent'

s.close()

Here the client also sends the size of the file. Both size and filesize are encoded as binary strings (you could do another method). The filename length (size) can take values up to 2^16 and the send file can have up to 2^32 byte (that is 2^filesize).

like image 71
Jesper Freesbug Avatar answered Oct 23 '22 05:10

Jesper Freesbug