Problems while implementing file transfer with sockets in Python - python

I am learning Python right now, and try to write a small file transfer program. The following is my codes.
This is the server codes
import SocketServer
import commands, time
class MySockServer(SocketServer.BaseRequestHandler):
def recv_all(self,obj, msg_length, des_file):
while msg_length != 0:
if msg_length <= 1024:
print 'here3'
print msg_length
print type(msg_length)
data = obj.recv(msg_length)
print data
msg_length = 0
print 'here4'
break
else:
data = obj.recv(1024)
msg_length -= 1024
#print msg_length
des_file.write(data)
print 'here4'
return 'Done'
def handle(self):
print 'Got a new conn from', self.client_address
while True:
cmd = self.request.recv(1024)#receive data from client
print cmd
if not cmd:#deal with ctrl+c from client
print 'Lost connection'
break
CMD = cmd.split()
print CMD
option, filename, file_size = CMD[:3]
print option
print filename
print file_size
if option == 'put':
#client wants to upload file
f = file('temp/%s' % filename, 'wb')
print 'here'
write_to_file = self.recv_all(self.request, int(file_size), f)
print 'here1'
if write_to_file == 'Done':
f.close()
self.request.send('File uploading done')
if __name__ == '__main__':
h = '0.0.0.0'
p = 9002
s = SocketServer.ThreadingTCPServer((h,p),MySockServer)
s.serve_forever()
The client codes:
import socket, os
host,port = '192.168.73.11', 9002
c = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
c.connect((host,port))
while True:
user_input = raw_input('msg to send:: ').strip()
if len(user_input) == 0: continue
user_cmd = user_input.split()
if user_cmd[0] == 'put':
if len(user_cmd) == 2:
f = file(user_cmd[1], 'rb')
f_size = os.path.getsize(user_cmd[1])
print user_cmd[0], user_cmd[1], str(f_size)
c.send('%s %s %s ' % (user_cmd[0],user_cmd[1],f_size))
print 'going to send....'
c.sendall(f.read())
print c.recv(1024)
c.close()
I just inserted some prints into the codes to find where are the problems. I found that in the recv_all() function in server codes, the sentence 'data = obj.recv(msg_length)' in the 'if' part cannot work, but the sentence in the 'else' part works very well. Is there anyone can tell me why could this happen?
Thanks guys.

Related

Simple Server file program, file always doesn't exist

i recently tried a tutorial on how to create a simple file server program with python. i don't know why everytime i check whether the file exists or not, it always tells me the file doesn't exist, here is the code
# server.py
import socket
import threading
import os
def RetFile(FileName, sock):
FileName = sock.recv(1024)
exists = os.path.isfile(FileName)
if exists:
sock.send(str.encode("EXISTS " + str(os.path.getsize(FileName))))
UserResponce = sock.recv(1024)
if UserResponce[:2] == "OK":
with open(FileName, 'rb') as f:
bytesToSend = f.read(1024)
sock.send(bytesToSend)
while bytesToSend != "":
bytesToSend = f.read(1024)
sock.send(bytesToSend)
else:
sock.send(str.encode("ERR"))
sock.close()
def Main():
host = '127.0.0.1'
port = 5001
s = socket.socket()
s.bind((host, port))
s.listen(5)
print('Server Started')
while True:
conn, addr = s.accept()
print('Client Connected -> ', str(addr))
t = threading.Thread(target=RetFile, args=("retrThread", conn))
t.start()
if __name__ == '__main__':
Main()
# client.py
import socket
def Main():
host = '127.0.0.1'
port = 5001
s = socket.socket()
s.connect((host, port))
filename = input('File Name -> ')
if filename != 'q':
s.send(str.encode(filename))
data = s.recv(1024)
if data[:6] == "EXISTS ":
filesize = float(data[6:])
message = input('File Exists: ' + str(filesize) + ' Bytes, Download? (Y/N) -> ')
if message == 'Y':
s.send(str.encode("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 Doesn't Exist")
s.close()
if __name__ == '__main__':
Main()
so where is the error of the code? the tutorial uses python 2.x and i use 3.x so i have some minor changes, and i'm new to this language so any help would be appreciated, thank you!
There were some issues in you code mostly related to byte conversion . you cannot send string on socket interface if you are using python 3 or above, with python 2 it works fine. So every message has to be changed to bytes before sending on socket i have fixed all such issues . Download is working fine
Fixed Server
# server.py
import socket
import threading
import os
def RetrFile(name, sock):
filename = sock.recv(1024)
if os.path.isfile(filename):
sock.send(b"Exist " + str(os.path.getsize(filename)).encode())
userResponse = sock.recv(1024)
if userResponse.decode() == 'OK':
with open(filename, 'rb') as f:
bytesToSend = f.read(1024)
while bytesToSend.decode() != "":
sock.send(bytesToSend)
bytesToSend = f.read(1024)
else:
sock.send(b"ERR")
sock.close()
def Main():
host = '127.0.0.1'
port = 5000
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()
if __name__ == '__main__':
Main()
Fixed Client
# client.py
import socket
def Main():
host = '127.0.0.1'
port = 5000
s = socket.socket()
s.connect((host, port))
filename = bytearray(input("filename.. ").encode())
if filename != 'q':
s.send(filename)
data = s.recv(1024)
if data[:6].decode().rstrip().upper() == 'EXIST':
filesize = data[6:].decode().rstrip()
message = input("File exists, " + filesize+ "Bytes, download..? (Y/N)")
if message.upper() == 'Y':
totalRecv = 0
s.send(b'OK')
f = open('new_' + filename.decode(), 'wb')
data = s.recv(1024)
while data.decode() != "":
totalRecv += len(data)
data = s.recv(1024)
f.write(data)
print("{:2f}".format((totalRecv/float(filesize))*100)+ "Done")
print("Download complete")
else:
print("File doesn't exist")
if __name__ == '__main__':
Main()
Apart from the fact that a file may not exist, there is one obvious problem:
if data[:6] == "EXISTS ":
can never be True because data[:6] is a string of 6 characters, and "EXISTS " is 7 characters long.

Tcp sockets to send and receive files, using python

I am trying to make simple client server program to send and receive file form server using tcp sockets. As far as getting files from server is not an issue, server creates a file with the same name and put data in that file but when it comes to putting files to server,sometimes it works great but always chance so mostly server is getting file name along with file contents and instead of writing that to file, it writes both filename and contents as new file name and that file remains empty. Will be great help if someone can suggest any solution.
server.py
import socket
import sys
HOST = 'localhost'
PORT = 3820
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.bind((HOST, PORT))
socket.listen(1)
while (1):
conn, addr = socket.accept()
print 'New client connected ..'
reqCommand = conn.recv(1024)
print 'Client> %s' %(reqCommand)
if (reqCommand == 'quit'):
break
#elif (reqCommand == lls):
#list file in server directory
else:
string = reqCommand.split(' ', 1) #in case of 'put' and 'get' method
reqFile = string[1]
if (string[0] == 'put'):
with open(reqFile, 'wb') as file_to_write:
data=conn.recv(1024)
while True:
if not data:
break
else:
file_to_write.write(data)
data=conn.recv(1024)
file_to_write.close()
break
print 'Receive Successful'
elif (string[0] == 'get'):
with open(reqFile, 'rb') as file_to_send:
for data in file_to_send:
conn.sendall(data)
print 'Send Successful'
conn.close()
socket.close()
client.py
import socket
import sys
HOST = 'localhost' # server name goes in here
PORT = 3820
def put(commandName):
socket1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket1.connect((HOST, PORT))
socket1.send(commandName)
string = commandName.split(' ', 1)
inputFile = string[1]
with open('clientfolder/'+inputFile, 'rb') as file_to_send:
data=file_to_send.read(1024)
while(data):
socket1.send(data)
data=file_to_send.read(1024)
file_to_send.close()
print 'PUT Successful'
socket1.close()
return
def get(commandName):
socket1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket1.connect((HOST, PORT))
socket1.send(commandName)
string = commandName.split(' ', 1)
inputFile = string[1]
with open('clientfolder/'+inputFile, 'wb') as file_to_write:
while True:
data = socket1.recv(1024)
# print data
if not data:
break
# print data
file_to_write.write(data)
file_to_write.close()
print 'GET Successful'
socket1.close()
return
msg = raw_input('Enter your name: ')
while(1):
print 'Instruction'
print '"put [filename]" to send the file the server '
print '"get [filename]" to download the file from the server '
print '"ls" to list all files in this directory'
print '"lls" to list all files in the server'
print '"quit" to exit'
sys.stdout.write('%s> ' % msg)
inputCommand = sys.stdin.readline().strip()
if (inputCommand == 'quit'):
socket.send('quit')
break
# elif (inputCommand == 'ls')
# elif (inputCommand == 'lls')
else:
string = inputCommand.split(' ', 1)
if (string[0] == 'put'):
put(inputCommand)
elif (string[0] == 'get'):
get(inputCommand)
#current working directory is server location
#get will get file from current directory to clientfolder directory.
TCP is a streaming protocol, so you have to design message breaks into your protocol. For example:
s.send('put filename')
s.send('data')
Can be received as:
s.recv(1024)
# 'put filenamedata'
So buffer data received and only extract full messages. One way is to send the size of a message before the message.

Not able to read input from client program

I am trying to write Client-server code. I have added a menu in client code. and depending on input from a client I tried to add cases in the server code. I am able to send the client selected choice to server code, but not able to select a case from the received data. Here is my code.
server.py
import socket
import sys
import os
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print (' socket created s1')
serveraddress = ('localhost' , 2000)
print ('starting server on', serveraddress)
s1.bind(serveraddress)
s1.listen(3)
while True:
print('waiting for connection')
connection, clientaddress = s1.accept()
print ('connecting with', clientaddress)
command = connection.recv(1000)
print (command)
if command == '1':
print('entered into 1st if')
try:
filename = connection.recv(1000)
with open(filename, 'rb') as filetosend:
for data in filetosend:
connection.sendall(data)
finally:
connection.close()
if command == '2':
print('entered into 2st if')
filelist = os.listdir('C:\Rahul')
connection.sendall(filelist)
if command == '3':
print('entered into 3st if')
s1.close()
break
Client.py
import sys
import os
import socket
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serveraddress = ('localhost' , 2000)
print ('connecting to server on'), serveraddress
s1.connect(serveraddress)
try:
a = input('Enter you choice: \n 1-Get file \n 2-Get List \n 3-quit \n')
while True:
if a == 1:
s1.send('1')
b = input('enter file name: ')
s1.send(b)
downloadDir = r'C:\Users\rahul\Desktop'
with open(os.path.join(downloadDir, b), 'wb') as filetowrite:
while True:
data = s1.recv(1000)
if not data:
break
filetowrite.write(data)
filetowrite.close()
s1.close()
elif a == 2:
s1.send('2')
#s1.sendall(' send all files list ')
filelist = s1.recv(1000)
print (filelist)
elif a == 3:
x = False
print('closing connection')
s1.close()
finally:
s1.close
Try adding except block too in client script, your code will work after that.
And I will suggest you to use raw_input for input purposes in sockets, and format the data type at input to avoid any error in program.
import sys, os, socket
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serveraddress = ('localhost' , 2000)
print ('connecting to server on'), serveraddress
s1.connect(serveraddress)
try:
a = int(raw_input('Enter you choice: \n 1-Get file \n 2-Get List \n 3-quit \n'))
while True:
if a == 1:
s1.send('1')
b = str(raw_input('enter file name: '))
s1.send(b)
# downloadDir = '\\root\\'
# with open(os.path.join(downloadDir, b), 'wb') as filetowrite:
# while True:
# data = s1.recv(1000)
# if not data:
# break
# filetowrite.write(data)
# filetowrite.close()
print "It worked till here."
s1.close()
elif a == 2:
# s1.send('2')
# #s1.sendall(' send all files list ')
# filelist = s1.recv(1000)
# print (filelist)
print "It also worked till here."
elif a == 3:
x = False
print "Closing Connection"
s1.close()
except:
print 'It Gave an Error'
This worked fine.

Python File Server, login function not working

I made a python file server a while back and just recently came back to it. It is a very simple program but i wanted to add some more features to it, one of those being to add some security. For this reason i made a hashed login password and put that in a .txt file stored on the server computer. The way the program is supposed to work is every time the client connects to the server they must enter a password. Then the raw_entry is sent through a socket and checked on the server side if it is correct, if is is not then the user has two more tries to enter the password. For some reason this is not working.
The server:
from passlib.hash import pbkdf2_sha256
import socket
import threading
import os
def login():
loop = 1
while loop <= 3:
passwd = sock.recv(1024)
with open('passtor.txt', 'r') as f:
hash = f.read()
if pbkdf2_sha256.verify(passwd, hash):
s.send("Access Granted")
loop = 4
else:
s.send("Verification Failure")
loop += 1
if loop == 3:
sock.close()
def RetrFile(name, sock):
filename = sock.recv(1024)
if os.path.isfile(filename):
sock.send("EXISTS " + str(os.path.getsize(filename)))
userResponse = sock.recv(1024)
if userResponse[:2] == 'OK':
with open(filename, 'rb') as f:
bytesToSend = f.read(1024)
sock.send(bytesToSend)
while bytesToSend != "":
bytesToSend = f.read(1024)
sock.send(bytesToSend)
else:
sock.send("ERR ")
sock.close()
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#s.connect(('google.com', 0))
host = s.getsockname()[0]
port = 5000
s = socket.socket()
s.bind((host,port))
s.listen(5)
print "File Server Initiated"
print("Server Address-> " + host + " <-")
while True:
c, addr = s.accept()
print "Client Connected ip-> " + str(addr) + " <-"
t1 = threading.Thread(target=login, args=("RetrThread", c))
t2 = threading.Thread(target=RetrFile, args=("RetrThread", c))
t1.start()
t2.start()
s.close()
except:
print("Program Error, \nTermination Complete")
The client:
import socket
host = '127.0.0.1'
port = 5000
s = socket.socket()
s.connect((host, port))
loop = True
while loop == True:
passwd = raw_input("Admin Password-> ")
s.send(passwd)
answer = s.recv(1024)
if answer == 'Verification Failure':
loop = True
print(answer)
elif answer == 'Access Granted':
loop = False
print(answer)
filename = raw_input("Filename? -> ")
if filename != 'q':
s.send(filename)
data = s.recv(1024)
if data[:6] == 'EXISTS':
filesize = long(data[6:])
message = raw_input("File exists, " + str(filesize) +"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!"
f.close()
else:
print "File Does Not Exist!"
s.close()
You are passing two arguments to the login function here:
t1 = threading.Thread(target=login, args=("RetrThread", c))
They are not declared in the function declaration:
def login():
Either remove the args parameter from the call to threading.Thread or add the arguments to the function declaration.

File Server Upload Python

File Server Download Problem Python 2.5.1
So i am working on a File Server as a hobby project. I am having some problems though. I can use the client to successfully upload the file to the server but say the file to upload is 50,000 bytes (50 mbs) it will only upload like 49,945 bytes then if i try opening it, it says its corrupt. If i close the server it goes to 50,000 then works. Is there a way to fix this without the server needing to close and reopen?
(Downloading Doesnt Have this Problem)
Full Client Code:
Client
Full Server:
Server
Client Upload Function:
def Uploader(s):
IsReal = True
data = "UploaderReady"
if data == "UploaderReady":
List = []
FilePath = dir_path = os.path.dirname(os.path.realpath(__file__))
List.append(os.listdir(FilePath))
FileUpload = raw_input("Pick a file? -> ")
for Item in List:
if FileUpload == Item:
IsReal = True #checks if item exists
if IsReal == True:
File = open(FileUpload,'rb')
bytestosend = File.read(1024)
FileSize = os.path.getsize(FileUpload)
s.send(FileUpload)
s.send(str(FileSize))
s.send(bytestosend)
while bytestosend != "":
bytestosend = File.read(8192)
s.send(bytestosend)
print"Processing"
File.close()
time.sleep(1.5)
s.send("COMPLETE")
print"File Successfully Uploaded"
time.sleep(2)
print" \n " * 10
Main()
if IsReal == "False":
print"Item doesn't Exist"
time.sleep(2)
print" \n " * 10
s.close()
Main()
Server Upload Function:
Todo = sock.recv(1024)
if Todo == "U":
print str(addr)+" Uploading"
UploadingThread = threading.Thread(target=Uploader,args=(c,c,))
UploadingThread.start()
def Uploader(c,s):
filename = s.recv(1024)
filesize = s.recv(1024)
f = open(filename,'wb')
totalRecv = 0
while totalRecv < filesize:
FileContent = s.recv(8192)
totalRecv += len(FileContent)
f.write(FileContent)
print"Download Complete"
f.close()
s.close()
You close the client connection on the server side, but never close it on the client side as Cory Shay said.
Instead of closing it though, you need to shutdown the socket and signal it is done writing with s.shutdown(socket.SHUT_WR)
Here's how it should look for the client:
def Uploader(s):
IsReal = True
data = "UploaderReady"
if data == "UploaderReady":
List = []
FilePath = dir_path = os.path.dirname(os.path.realpath(__file__))
List.append(os.listdir(FilePath))
FileUpload = raw_input("Pick a file? -> ")
for Item in List:
if FileUpload == Item:
IsReal = True #checks if item exists
if IsReal == True:
File = open(FileUpload,'rb')
bytestosend = File.read(1024)
FileSize = os.path.getsize(FileUpload)
s.send(FileUpload)
s.send(str(FileSize))
s.send(bytestosend)
while bytestosend != "":
bytestosend = File.read(8192)
s.send(bytestosend)
print"Processing"
s.shutdown(socket.SHUT_WR) # End the writing stream
print(s.recv(1024)) # Expecting the server to say 'upload complete'
s.close() # close the socket
File.close()
time.sleep(1.5)
s.send("COMPLETE")
s.close() #To close connection after uploading
print"File Successfully Uploaded"
time.sleep(2)
print" \n " * 10
Main()
and the server:
def Uploader(c,s):
filename = s.recv(1024)
filesize = s.recv(1024)
f = open(filename,'wb')
totalRecv = 0
while totalRecv < filesize:
FileContent = s.recv(8192)
totalRecv += len(FileContent)
f.write(FileContent)
s.send("Upload Complete!") # Tell client the upload is complete
print"Download Complete"
f.close()
s.close() # Close the socket
Also, you are passing the server Uploader 2 identical arguments, and only using one, instead you should just pass one:
UploadingThread = threading.Thread(target=Uploader,args=(c,c,))
# should be
UploadingThread = threading.Thread(target=Uploader,args=(c,))
Similarly, your password thread only needs 2:
c, addr = s.accept()
print"Client Connection: <"+str(addr)+">"
PasswordThread = threading.Thread(target=Password,args=(c,addr))
def Password(c,addr):
c.send("WAITINGPASSWORD")
PASSWORD = "123"
password = c.recv(1024)
and your checking password function can be simpler:
def Password(c,addr):
password = "123"
c.send("WAITINGPASSWORD")
attempt = c.recv(1024)[::-1]
if attempt == password:
doStuff()

Categories