Upload files from client to server and vice versa in python - python

Started to implement this project in C++, however I figured Python would be a better choice going forward for x-platform.
Goal here is to create a simple file server and then create a client. Client should be able to upload files to the server and download files from the server.
My code for the client is:
import socket
def Main():
host = '127.0.0.1'
port = 5000
s = socket.socket()
s.connect((host,port))
choice = raw_input("Upload or Download? (u/d):")
if choice == 'd':
filename = raw_input("File to Download? (q to quit): ")
if filename != 'q':
s.send(filename)
data = s.recv(1024)
if data[:6] == "EXISTS":
filesize = long(data[6:])
message = raw_input("File found on the server!," +str(filesize)+"bytes, continue with 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 ("Percentage Completed: "+"{0:.2f}".format((totalRecv/float(filesize))*100))
print ("File has been Downloaded!")
else:
print ("File doesnt exist!")
else:
filename = raw_input("File to Upload? (q to quit): ")
# if filename != 'q':
print ("Upload Function Coming Soon")
s.close()
if __name__ == '__main__':
Main()
The code for the server is:
import socket
import threading
import os
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()
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:") + str(addr) + ">"
t = threading.Thread(target=RetrFile, args=("retrThread", c))
t.start()
s.close()
if __name__ == '__main__':
Main()
I have it just fine for the download of the file, and thinking about it, I should be able to just reverse process for the upload portion of the client (instead of fetch the download, I basically copy the server part to perform the upload)...however I just cant seem to wrap my head around how to do so. I'm not worried at this point over the hard coded port etc---will fix that later, however does anyone have any suggestions going forward with this?
I need to emphasize that I am using python < v3 (I know--its old) however its a program limitation that I need to adhere to (hence the raw_input() v. input())

Related

Sending Zip folder over Python sockets

So for some reason this code is not properly working for sending a zip folder from the client to server. on the server side if I use "f = zipfile.ZipFile("platformIO.zip")" I get the error "ValueError: stat: embedded null character in path", and if I use "f = open("platformIO.zip", "wb")" no error is thrown but the received file is corrupt and won't open.
I have read every similar to question to this and cannot find a solution.
Client:
import socket
import time
# Configure wireless connection with server (board on leg)
HOST = "192.168.4.1" # change to server ip address
PORT = 5005 # must be same as server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
print("connected")
user_input = "startup"
while True:
if user_input == "startup":
# ask if user wants to send code
user_input = input("Do you want to send new code?: (y/n)")
if user_input == "y":
user_input = "send code"
elif user_input == "n":
user_input = input("Would you like to collect data?: (y/n)")
if user_input == "y":
user_input = "receive data"
else:
user_input = "startup"
else:
user_input == "startup"
elif user_input == "send code":
st = "sending code"
s.send(st.encode())
file = "platformIO.zip"
try:
with open(file, "rb") as f:
print("sending file...")
data = f.read()
s.sendall(data)
print("finished sending")
st = "finished"
s.send(st.encode())
user_input = "startup"
except:
print("Failed transfering <platformIO.zip>, make sure it exists")
st = "failed"
s.send(st.encode())
elif input =="receive data":
print("feature not yet implemented")
user_input == "startup"
# delay
time.sleep(0.1)
Server:
import socket
import time
import zipfile
import os
# create server
HOST = "192.168.4.1"
PORT = 5005
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("socket created")
# managing error exception
try:
s.bind((HOST,PORT))
except socket.error:
print("bind Failed")
s.listen(1)
print("Socket awaiting mesesages")
(conn, addr) = s.accept()
print("connected")
# awaiting message
msg = "startup"
while True:
if msg == "startup":
# receive data from controller
msg = conn.recv(4096)
print(str(msg, 'utf-8'))
elif str(msg, 'utf-8') == "sending code":
f = zipfile.ZipFile("platformIO.zip", "w")
#f = open("platformIO.zip", "wb")
while True:
data = conn.recv(4096)
print(data)
if not data:
break
f.write(data)
print("file received")
msg = "startup"
time.sleep(.1)
conn.close()
edit: if I use f = open("platformIO.zip", "wb") and add s.close() inside the writing while loop of the server, I can receive the zip successfully, but then the connection closes and I can't open the zip file until I close the program
f = open("platformIO.zip", "wb")
while True:
data = conn.recv(4096)
print(data)
if not data:
break
f.write(data)
s.close()

Python File Server Only Works with One Thread Running

I have made a file server on python using sockets and threads. The program is supposed to allow the client to upload and download files from the server.
The program works perfectly when only one thread is running, but when both threads are running the server gives an error when trying to upload a file, and when trying to download the program just stops doing anything after the client enters 'Y' to initiate the download.
Here is the code for the client:
import socket
import os
def DownloadFile(s, host, port):
s.connect((host, port))
s.send(str.encode('DNLD'))
filename = input('Filename? ->')
if filename != 'q':
s.send(str.encode(filename))
data = s.recv(2048).decode('UTF-8')
if data[:6] == 'EXISTS':
filesize = data[6:]
message = input('File Exists, ' + str(filesize) + ' Bytes. Download? (Y/N) ->')
if message == 'Y' or message == 'y':
s.send(str.encode('OK'))
f = open('copy of '+filename, 'wb')
data = s.recv(2048)
totalRecv = len(data)
f.write(data)
while totalRecv < int(filesize):
data = s.recv(2048)
totalRecv += len(data)
f.write(data)
print('{}'.format(round((totalRecv/float(filesize))*100),2)+'% Complete')
print('Download Complete!')
s.close()
else:
print('File does not exist')
s.close()
Main()
def UploadFile(s, host, port):
s.connect((host, port))
s.send(str.encode('UPLD'))
filename = input('Filename? ->')
if os.path.isfile(filename):
filesize = os.path.getsize(filename)
filesize = str(filesize)
s.send(str.encode('EXISTS ' + filename))
s.send(str.encode(filesize))
ready = input('Ready to upload. Proceed? (Y/N) ->')
if ready == 'Y' or ready == 'y':
s.send(str.encode('OK'))
with open(filename, 'rb') as f:
bytesToSend = f.read(2048)
s.send(bytesToSend)
while bytesToSend != '':
bytesToSend = f.read(2048)
s.send(bytesToSend)
s.close()
else:
print('File does not exist.')
s.close()
Main()
def Main():
host = '127.0.0.1'
port = 10000
s = socket.socket()
while True:
choice = int(input('Please enter your choice:\n\n1. Upload a file to the server.\n2. Download a file from the server\n3. Quit.\n\n->'))
if choice == 1:
UploadFile(s, host, port)
break
elif choice == 2:
DownloadFile(s, host, port)
break
elif choice == 3:
s.close()
break
else:
print('Please enter a valid choice.')
if __name__ == '__main__':
Main()
And here is the code for the server:
import socket
import threading
import os
def SendFile(name, s):
check = s.recv(2048).decode('UTF-8')
if check == 'DNLD':
filename = s.recv(2048)
if os.path.isfile(filename):
send = os.path.getsize(filename)
send = str(send)
s.send(str.encode('EXISTS ' + send))
userResponse = s.recv(2048)
userResponse = userResponse.decode('UTF-8')
if userResponse[:2] == 'OK':
with open(filename, 'rb') as f:
bytesToSend = f.read(2048)
s.send(bytesToSend)
while bytesToSend != '':
bytesToSend = f.read(2048)
s.send(bytesToSend)
else:
s.send(str.encode('ERR'))
s.close()
def ReceiveFile(name, s):
check = s.recv(2048).decode('UTF-8')
if check == 'UPLD':
data = s.recv(2048).decode('UTF-8')
if data[:6] == 'EXISTS':
filename = data[6:]
data = s.recv(2048).decode('UTF-8')
filesize = data
userResponse = s.recv(2048)
userResponse = userResponse.decode('UTF-8')
if userResponse[:2] == 'OK':
f = open('copy of '+filename, 'wb')
data = s.recv(2048)
totalRecv = len(data)
f.write(data)
while totalRecv < int(filesize):
data = s.recv(2048)
totalRecv += len(data)
f.write(data)
print('Download Complete!')
def Main():
host = '127.0.0.1'
port = 10000
s = socket.socket()
s.bind((host, port))
s.listen(5)
print('Server Started')
while True:
c, addr = s.accept()
print('Client Connected: ' + str(addr))
Send = threading.Thread(target=SendFile, args=('sendThread', c))
Send.start()
Receive = threading.Thread(target=ReceiveFile, args=('retrThread', c))
Receive.start()
s.close()
if __name__ == '__main__':
Main()
If I were to comment out Send.start() or Receive.start() then whatever thread isn't commented out would work perfectly.
Here is the error given in the server when trying to upload a file with both threads running:
Exception in thread Thread-2:
Traceback (most recent call last):
File "C:\Python34\lib\threading.py", line 920, in _bootstrap_inner
self.run()
File "C:\Python34\lib\threading.py", line 868, in run
self._target(*self._args, **self._kwargs)
File "(file location)", line 28, in ReceiveFile
check = s.recv(2048).decode('UTF-8')
OSError: [WinError 10038] An operation was attempted on something that is not a socket
And here is the output in the client when trying to download a file when both threads are running:
Please enter your choice:
1. Upload a file to the server.
2. Download a file from the server
3. Quit.
->2
Filename? ->cat.jpg
File Exists, 10634 Bytes. Download? (Y/N) ->Y
Nothing else happens after entering Y.
If anyone knows what is going wrong I would really appreciate some help.
That's not the way io and threads work. You have here 2 threads competing from the same input data. One will get first packet be it for it or not, and it is likely that one of the following packet will be eaten by the other thread => the first one will never see it!
You can delegate the processing of a conversation to a thread but to a single one that will call a send or receive function once it will have identified the request.
That is not all. TCP is a stream protocol. Packets can be splitted or re-assembled by any piece along the connection (sender, receiver and any gateway). So you should use delimiters to tell the peer that a name or a command if complete. And good practices recommend to pass the size when sending binary data, here again for the peer to know when the data is complete.
Good luck in your journey is the socket world ;-)

Type Error using Socket communication even while decoding to byte string

Hello I got a problem with a type error I cant get rid off.
I have build a server named processA.py and a client processB.py
I start the server calling processA and it starts up
I start the client calling processB and it starts up
Now I input the name of the file I want to send over a socket.
The image must be in the same folder as the programms.
You can use the sample code from below for reproducing the error.
I choose: lena.jpg
I get an error in line 15, in of my processA.py:
sock.send("EXISTS" + str(os.path.getsize(filenameByte))) TypeError: a
bytes-like object is required, not 'str'
processA.py
'''
Created on 29 Nov 2017
#author: Poor Student
'''
import numpy
import socket
import threading
import os
def RtrFile(name, sock):
filenameByte = sock.recv(1024)
filenameStr = filenameByte.decode('ascii')
if os.path.isfile(filenameStr):
sock.send("EXISTS" + str(os.path.getsize(filenameByte)))
userResponse = sock.recv(1024)
if userResponse[:2] == 'OK':
with open(filenameByte, '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()
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 = RtrFile, args=("rtrThread",c))
t.start()
s.close()
if __name__ == "__main__":
Main()
processB.py
'''
Created on 29 Nov 2017
#author: Poor Student
'''
import socket
def Main():
host = "127.0.0.1"
port = 5000
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 = int(data[6:])
message = input("File Exists, " +str(filesize) + "Bytes, download? (Y/N)? ->")
if message == "Y" or 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:.f)".format((totalRecv)/float(filesize))*100 +"done")
print("Download Complete")
else:
print("File does not exists")#
s.close()
if __name__ == "__main__":
Main()
I found an answer. In python 3 you have allways convert your Strings to byte strings when sending them. After sending them to the receiver you have to decode them again and this must be done for the hole communication which is why the error allways shows up in the same module.
Process A:
'''
Created on 29 Nov 2017
#author: Happy student
'''
import numpy
import socket
import threading
import os
from idlelib.IOBinding import encoding
def RtrFile(name, sock):
filenameByte = sock.recv(1024)
filenameStr = filenameByte.decode('ascii')
print("FilenameStr",filenameStr)
if os.path.isfile(filenameStr):
print("Type:",type(filenameByte))
print(os.path.getsize(filenameByte))#
sendStr = "EXISTS" + str(os.path.getsize(filenameByte))
#Convert the string to byte because otherwise it will not be send
sock.send((sendStr.encode(encoding)))
userResponse = sock.recv(1024)
#the Responce will be received in byte and will be converted to a string to make it checkable
userResponceStr = userResponse.decode('ascii')
if userResponceStr[:2] == 'OK':
with open(filenameByte, 'rb') as f:
bytesToSend = f.read(1024)
sock.send(bytesToSend)
while bytesToSend != "":
bytesToSend = f.read(1024)
sock.send(bytesToSend)
else:
print("User response not known")
else:
sendStr = "ERR"
sock.send(sendStr.encode(encoding))
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 = RtrFile, args=("rtrThread",c))
t.start()
s.close()
if __name__ == "__main__":
Main()
processB.py
'''
Created on 29 Nov 2017
#author: Happy student
'''
import socket
from idlelib.IOBinding import encoding
def Main():
host = "127.0.0.1"
port = 5000
s = socket.socket()
s.connect((host,port))
filename = input("Filename? -> ")
if filename != "q":
s.send(filename.encode())
data = s.recv(1024)
dataStr = data.decode('ascii')
if dataStr[:6] == "EXISTS":
filesize = int(dataStr[6:])
message = input("File Exists, " +str(filesize) + "Bytes, download? (Y/N)? ->")
if message == "Y" or message =="y":
sendStr = "OK"
s.send(sendStr.encode(encoding))
#create new file new_filename and
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("Download Complete")
else:
print(message +"was not noticed")
exit()
else:
print("File does not exists")#
s.close()
if __name__ == "__main__":
Main()

Python file server

I followed a tutorial to make this, and I'm trying to add an ls command so you can see the files to download. The code works, and all the prints return the right things, but the client only shows six letters of one of the files.
Server:
import socket
import threading
import os
def RetrFile(name, sock):
filename = sock.recv(1024)
if filename != "ls":
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()
else:
dir_path = os.path.dirname(os.path.realpath(__file__))
retval = os.listdir(dir_path)
print retval
for ret in retval:
print ret
sock.send(ret)
def Main():
host = '192.168.0.125'
port = 5000
s = socket.socket()
s.bind((host,port))
s.listen(5)
print "Server Started."
while True:
c, addr = s.accept()
print "client connedted ip:<" + str(addr) + ">"
t = threading.Thread(target=RetrFile, args=("RetrThread", c))
t.start()
s.close()
if __name__ == '__main__':
Main()
Directory with the Python file (files to download): directory
Server Output: "client connedted ip:<('192.168.0.112', 49546)>
['runmeee.exe', 'Untitled.png', 'putty.exe', 'pyserver.py']
runmeee.exe
Untitled.png
putty.exe
pyserver.py"
Client output: runmee

Python Socket Handling Multiple Connection

I'd like to let more than one client connect to my server, and have the server send them different items. For example send "hi" to the first client and "goodbye" to the second . Here's my code:
Server
import socket
file_num = 0
inp = raw_input("Name of the wordlist file = ")
inp2 = input("Number of lines for every wordlist = ")
with open(inp) as in_file:
for line_num, line in enumerate(in_file):
print line_num
if not line_num % inp2:
file_num += 1
with open("out{0}.txt".format(file_num), "a") as out_file:
out_file.writelines(line)
def upload(host, port):
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((host, port))
server_socket.listen(5)
filename = open("out1.txt", "rb")
print "Server Waiting for client on port ", port
while 1:
client_socket, address = server_socket.accept()
print "Connection from ", address
while 1:
for line in filename:
server_data = line
if server_data.lower() == 'q':
client_socket.send(server_data)
client_socket.close()
break
else:
client_socket.send(server_data)
client_data = client_socket.recv(1024)
if client_data.lower() == 'q':
print "Quit from client"
client_socket.close()
break
else:
print "<-- client: ", client_data
break
upload("localhost", 4000)
and then my client program
Client
import socket
port = 4000
host_server = "localhost"
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((host_server, port))
z = 1
print "Type 'Q' or 'q' to QUIT"
f = open("pino.txt", "w")
while 1:
server_data = client_socket.recv(1024)
f.writelines(server_data)
if server_data.lower() == 'q':
print "Quit from server"
client_socket.close()
break
else:
print "<-- server: ", server_data
client_data = ("Sent "+str(z))
z = z+1
if client_data.lower() != 'q':
client_socket.send(client_data)
else:
client_socket.send(client_data)
client_socket.close()
break
f.close()
Hope you give me the solution cause this will be cool if it works, another thing I'd like for this program is if the filename under def upload would change for every client. For example the first client will get out1 and the 7th will get out7. Thanks in advance.
P.S. I'm new to python so if you could explain me what you changed it would be great, don't ask me to use Twisted cause Id like to do this with the normal python socket .
I've had this problem myself :-)
So what you're trying to do is have multiple connections, however usually socket uses the main thread, making it hard to have more than one connection.
To fix this we need to use something called Threading, it allows you to surpass operations onto other threads. So you need to create a new thread when every connection is made:
import socket
from _thread import *
file_num = 0
inp = raw_input("Name of the wordlist file = ")
inp2 = input("Number of lines for every wordlist = ")
with open(inp) as in_file:
for line_num, line in enumerate(in_file):
print line_num
if not line_num % inp2:
file_num += 1
with open("out{0}.txt".format(file_num), "a") as out_file:
out_file.writelines(line)
def upload(host, port):
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((host, port))
server_socket.listen(5)
filename = open("out1.txt", "rb")
print "Server Waiting for client on port ", port
while 1:
client_socket, address = server_socket.accept()
print "Connection from ", address
while 1:
for line in filename:
server_data = line
if server_data.lower() == 'q':
client_socket.send(server_data)
client_socket.close()
break
else:
client_socket.send(server_data)
client_data = client_socket.recv(1024)
if client_data.lower() == 'q':
print "Quit from client"
client_socket.close()
break
else:
print "<-- client: ", client_data
break
start_new_thread(upload, ("localhost", 4000))
#NOTICE!!! If this line doesn't work ^^^
#Then replace it with:
#thread.start_new_thread(upload, ("localhost", 4000))
Hope this helps! :-)
Please tell me if it doesn't,
for I have not tested this, I've just done it before :)
Thanks,
~Coolq

Categories

Resources