Send and recieve files in python - python-3.x

So, I am making something in my computer science class where you can send files to a remote server and that works, but cant recv them back.
SERVER.PY
import socket # Import socket module
import os #imports os module
def RecvFile():
while True: # allows it to always save files and not have to be restarted.
c, addr = s.accept()
print ('Connection Accepted From',addr)# this prints out connection and port
print ("File is comming ....")
file = c.recv(1024) #recieves file name from client
f = open(file,'wb') #open that file or create one
l = c.recv(1024) #now recieves the contents of the file
while (l):
print ("Receiving...File Data")
f.write(l) #save input to file
l = c.recv(1024) #get again until done
print("The file",file,"has been succesfully saved to the server\nConnection from:",addr)
f.close()
def SendFile():
c, addr = s.accept()
print("Connection Accepted From",addr)
filename = c.recv(1024)
if os.path.isfile(filename):
s.send("EXISTS"+str(os.pthat.getsize(filename)))
response = c.recv(1024)
if response[:2] == 'OK':
with open(filename, 'rb') as f:
s.sendall(f.read)
f.close()
else:
s.send("ERR")
s.close()
def main():
s = socket.socket()
s.bind(('139.59.173.187', 8000)) # Binds port and IP address
s.listen(3)
print("Server Started")
while True:
c, addr = s.accept()
option = c.recv(1024)
if option == "S":
RecvFile()
elif option == "R":
SendFile()
else:
s.send("Incorrect input".encode('utf-8'))
main()
#if errors occur
c.close()
I think the server.py is the problem
Client .py
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('139.59.173.187',8000))
print("=========================Welcome to the File System =========================")
option = input("Here are your options:\n--> Press S to upload files\n--> Press R to retrieve files")
if option == "S" or option == "s":
s.send("S".encode('utf-8'))
file_name = input("Please input the file name\n>>>")
name = input("What would you like it to be saved as?\n>>>")
s.send(name.encode('utf-8'))
with open(file_name,'rb') as f:
s.sendall(f.read())
print("File has been sent to the server")
main()
elif option == "R" or option == "r":
s.send("R".encode('utf-8'))
filename = input("What is the filename you wish to recieve\n>>>")
s.send(filename.encode('utf-8'))
print ("File is comming ....")
f = open(filename,'wb') #open that file or create one
l = c.recv(1024) #now recieves the contents of the file
while (l):
print ("Receiving...File Data")
f.write(l) #save input to file
l = c.recv(1024) #get again until done
print("The file",filename,"has been succesfully saved to your computer")
f.close()
I have put 7 hours into learning this and the asignment is due in friday. rather than saying the code could you comment how it works etc.

In server.py, SendFile and RecvFile both use a socket object s that they have no access to. I recommend that you pass it as an argument :
def RecvFile(s):
#...
def SendFile(s):
#...
And then in main :
if option == "S":
RecvFile(s)
elif option == "R":
SendFile(s)

Related

loop doesn't break up when receiving data from client even i wrote break

Hi everyone I decided to create a program that transfer files between client and server, but the problem is the loop won't break its looks like he's still waiting for data to receive, even I wrote (if not data: break)
I received the file successfully, but it's not back to the outer loop any help and thank you.
while True:
###server side
cmd = input("enter msg command :")
client_socket.send(cmd.encode())
if cmd.startswith("download"):
filename = cmd.strip("download ")
with open(filename, 'wb') as f:
print("Downloading file...")
while True:
data = client_socket.recv(4096)
if not data:
break
f.write(data)
print("Successfully downloaded")`
#####clientside
while True:
command = s.recv(1024)
command = command.decode()
if command.startswith("download"):
print("True\n")
filename = command.strip("download ")
with open(filename,'rb') as f:
print("file sending.....")
while True:
data = f.read(4096)
if not data:
break
s.sendall(data)
print("file has sent")

How to tell a client that a file doesn't exist in the server in Python

I'm writing a simple client-server simple application, in which the client requests a certain file to the server. If the file exists, the server sends the file and its size; if it doesn't exists, then the server sends a message to the client saying the file couldn't be found. I included the exception in the server, but I don't know how to include the if clause in the client: if the file exists, the receive the file; else, receive the message saying it doesn't exist. I think I managed to do this on the server side, but I'm not really sure of how may I write this code to only print the message "file not found" in the client if the file wasn't found in the server
Here's the server side code
import socket
import os
import sys
import pickle
def Main():
host = '127.0.0.1'
port = 8881
s = socket.socket()
s.bind((host,port))
print("Server", host, "waiting on port", port)
s.listen(1)
while True:
c, addr = s.accept()
print("Connected to: " + str(addr))
filename = ''
while True:
data = c.recv(1024).decode('utf-8')
if not data:
break
filename += data
print("File requested: " + filename)
if os.path.isfile(filename):
lista = []
myfile = os.path.getsize(filename)
size = ('File size: ',myfile,' bytes')
texto = ''
for i in size:
texto = texto + '{:>4}'.format(i)
print(texto)
lista.append(texto)
file_size = pickle.dumps(lista)
c.send(file_size)
file2send = open(filename, "rb")
c.send(file2send.read())
c.close()
else:
print("File not found")
msg = ('File not found')
s.send(msg.encode('utf-8'))
if __name__ == '__main__':
Main()
And the client side:
import socket, os.path, datetime, sys, pickle
def Main():
host = '127.0.0.1'
port = 8881
s = socket.socket()
s.connect((host, port))
Filename = input("File name and extension: ")
s.send(Filename.encode('utf-8'))
s.shutdown(socket.SHUT_WR)
file_size = s.recv(1024)
lista = pickle.loads(file_size)
print(lista)
data = s.recv(1024).decode('utf-8')
print(data)
msg = s.recv(1024).decode('utf-8')
print(msg)
s.close()
if __name__ == '__main__':
Main()
In server, you are sending "file not found" message to server socket s, instead you should send that to client c and as per your logic you should send message length first and then message before closing the connection.
Please refer below server code.
Server:
import socket
import os
import sys
import pickle
def Main():
host = '127.0.0.1'
port = 8881
s = socket.socket()
s.bind((host,port))
print("Server", host, "waiting on port", port)
s.listen(1)
while True:
c, addr = s.accept()
print("Connected to: " + str(addr))
filename = ''
while True:
data = c.recv(1024).decode('utf-8')
if not data:
break
filename += data
print("File requested: " + filename)
if os.path.isfile(filename):
lista = []
myfile = os.path.getsize(filename)
size = ('File size: ',myfile,' bytes')
texto = ''
for i in size:
texto = texto + '{:>4}'.format(i)
print(texto)
lista.append(texto)
file_size = pickle.dumps(lista)
c.send(file_size)
file2send = open(filename, "rb")
c.send(file2send.read())
c.close()
else:
print("File not found")
msg = ('File not found')
c.send(str(len(msg)).encode('utf-8'))
c.send(msg.encode('utf-8'))
c.close()
if __name__ == '__main__':
Main()

Unicode error for python echo server when "Ctrl+C" pressed

I have created python echo server. The echo server can be started using command
sudo python3.8 echo_server.py
The client can be connected to it using command
telnet localhost 5000
I have implemented some commands like time,exit and network (i.e. if you type 'time' command on telnet client, the server responds with system time.)
For "network" command contain 3 while loops (i.e 1 loop for selecting network type, 2 loop for selecting static\dynamic, 3 loop for configuring ssid/password for wifi settings).
Now while configuring ssid/pwd, I wanted to go back to main command prompt for telnet client (i.e. where we can enter time,network command) on press of "Ctrl+c". But I am not able to handle the "Ctrl+c" on the echo server.I am getting below exception when "Ctrl+c" is pressed on telnet client
Exception in thread MyThread:
Traceback (most recent call last):
File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
self.run()
File "echo_server.py", line 47, in run
tx_data = ""
File "/usr/lib/python3.8/codecs.py", line 322, in decode
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
Main Terminating...
Please find my echo_server.py file
import socket
import os
import os.path
import subprocess
import time
from subprocess import Popen, PIPE, STDOUT
from threading import Thread
from time import sleep
class MyThread(Thread):
def __init__(self, val):
''' Constructor. '''
Thread.__init__(self)
self.val = val
class Filter:
"""Substitute \n with \r\n in stream output to terminal."""
def __init__(self, file):
self.file = file
def write(self, data):
self.file.write(data.replace("\n", "\r\n"))
def run(self):
while True:
HOST = '' # Symbolic name meaning all available interfaces
PORT = 5000 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
s.bind((HOST, PORT))
s.listen(5)
except socket.error:
time.sleep(5)
continue
conn, addr = s.accept()
file = conn.makefile(mode="rw")
filtered_file =MyThread.Filter(file)
file.flush()
filtered_file.write("Enter 'help' to list all valid commands\n")
while True:
file.write("Command> ")
file.flush()
data = file.readline()
tx_data = ""
if not data: break
data = data.strip()
if not data:
continue
elif data == 'time':
f= os.popen('date')
date=f.read().strip()
tx_data = date + '\n'
elif data == "network":
while True:
file.write("1. WiFi\n")
file.flush()
file.write("2. Ethenet\n")
file.flush()
file.write("3. Exi\n")
file.flush()
file.write("Enter a choice:")
file.flush()
choice = file.readline()
choice = choice.strip()
if choice == "1":
while True:
file.write("1. DHCP\n")
file.flush()
file.write("2. Static\n")
file.flush()
file.write("3. Exit\n")
file.flush()
file.write("Enter a choice:")
file.flush()
subchoice = file.readline()
subchoice = choice.strip()
if subchoice == "1":
while True:
file.write("Enter ssid:")
file.flush()
ssid = file.readline()
ssid = ssid.strip()
file.write("Enter pwd:")
file.flush()
pwd = file.readline()
pwd = pwd.strip()
break
break
elif choice == "2":
break
elif choice == "3":
break
else:
break
elif data == 'help':
tx_data = '''Valid commands are as below:
Enter number against the command for execution
1. time
2. network
3. exit\n'''
elif data == 'exit':
break
else:
tx_data = "Unknown Command: " + data + \
"\nEnter 'help' for list of valid commands\n"
filtered_file.write(tx_data)
#print 'Closing connection with client'
file.close()
conn.close()
# Run following code when the program starts
if __name__ == '__main__':
# Declare objects of My Thread class
my_obj = MyThread(4)
my_obj.setName('MyThread')
# Start running the threads!
my_obj.start()
# Wait for the threads to finish...
my_obj.join()
print('Main Terminating...')
I am not sure how to handle "Ctrl+c" so that control is back at the prompt when we can enter command.
Please let me know if any one has any suggestion to resolve this.
Here is my version of your program:
# echo_server.py
import socket
import os
import os.path
import subprocess
import time
from subprocess import Popen, PIPE, STDOUT
from threading import Thread
from time import sleep
def getcommand(thisfile, thisprompt, stripped=True):
thisfile.write(thisprompt)
thisfile.flush()
command = thisfile.readline()[:-1]
# print(f"{len(command)} chars received") # just for debug
# for i in command:
# print(ord(i))
if stripped:
return command.strip()
return command
class MyThread(Thread):
def __init__(self, val):
''' Constructor. '''
Thread.__init__(self)
self.val = val
class Filter:
"""Substitute \n with \r\n in stream output to terminal."""
def __init__(self, file):
self.file = file
def write(self, data):
self.file.write(data.replace("\n", "\r\n"))
def run(self):
while True:
HOST = '' # Symbolic name meaning all available interfaces
PORT = 5000 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
s.bind((HOST, PORT))
s.listen(5)
except socket.error:
time.sleep(5)
continue
conn, addr = s.accept()
file = conn.makefile(mode="rw", encoding="UTF-8", errors="ignore")
filtered_file = MyThread.Filter(file)
file.flush()
filtered_file.write("Enter 'help' to list all valid commands\n")
while True:
data = getcommand(file, "Command> ", stripped=False)
tx_data = ""
if not data:
print("No Command!")
break # closing connection
data = data.strip()
if not data:
print("Just Spaces!")
continue
elif data == 'time':
f= os.popen('date')
date=f.read().strip()
tx_data = date + '\n'
elif data == "network":
while True:
file.write("1. WiFi\n")
file.flush()
file.write("2. Ethernet\n")
file.flush()
file.write("3. Exit\n")
file.flush()
choice = getcommand(file, "Enter a choice:")
if choice == "1":
while True:
file.write("1. DHCP\n")
file.flush()
file.write("2. Static\n")
file.flush()
file.write("3. Exit\n")
file.flush()
subchoice = getcommand(file, "Enter a choice:")
if subchoice == "1":
while True:
ssid = getcommand(file, "Enter ssid:")
pwd = getcommand(file, "Enter password:")
if ssid and pwd:
break
break
elif choice == "2":
break
elif choice == "3":
break
elif data == 'help':
tx_data = '''Valid commands are as below:
Enter number against the command for execution
1. time
2. network
3. exit\n'''
elif data == 'exit':
break
else:
tx_data = "Unknown Command: " + data + \
"\nEnter 'help' for list of valid commands\n"
filtered_file.write(tx_data)
print('Closing connection with client')
file.close()
conn.close()
# Run following code when the program starts
if __name__ == '__main__':
# Declare objects of My Thread class
my_obj = MyThread(4)
my_obj.setName('MyThread')
# Start running the threads!
my_obj.start()
# Wait for the threads to finish...
my_obj.join()
print('Main Terminating...')
I made a new function to handle the input of text from the terminal. This function strips the new line char appended by readline() and optionally strips leading and trailing blanks from the input string. This enables your choice to close the connection if the user enters no data, while keeping it open and repeating the prompt if s/he just enters whitespace.
I also used the 'errors' optional argument in conn.makefile(), to avoid the UnicodeDecodeError, and added a line to repeat the input of ssid and password if either is blank. I also removed the else clause when the main choice is "network", to let the user out only by choosing 3.
With this version, there's no need to use Ctrl-C (that also has a meaning as KeyboardInterrupt) and if the user entered it, it wouldn't disrupt the server anymore.
Now, if you press Ctrl-C in the client, you stop receiving the server's output, but if you blindly enter the "exit" choices you get out of the connection gracefully.
Because ctrl-c not a unicode character and _io.TextIOWrapper (your file variable) can't handle it in unicode mode.
You can initialize wrapper in non unicode mode
file = conn.makefile(mode="rw",encoding='latin-1')
This will not disconnect client by ctrl-c and you should handle all special characters by your self (because telnet will still send it)
I changed your code to handle decoder errors as is. This will disconnect client on ctrl-c
while True:
file.write("Command> ")
file.flush()
try:
data = file.readline()
except UnicodeDecodeError as e:
conn.close()
break;
tx_data = ""
#if not data: break <-- This will throw error data undefined
data = data.strip()
Actually better solution not to use text wrapper at all
data = conn.recv(1024)
if not data: break
you have to initialize wrapper in other encoding type, use encoding = "latin-1"

Can't write data in text file through Python script

I'm using Python 3.6.4. I'm trying to send the file on a network.
Here is my code. When I try to execute it, it goes to infinite loop and my file remains 0kb.
f = open(f_name+'.txt', 'wb')
while True:
conn, addr = s.accept()
data = conn.recv(1024)
if data == "":
break
f.write(data)
f.close()
print("File closed")
conn.close()
Try something like this where you explicitly return False instead of break. Also, I'd open your connection outside of the while loop to make sure you aren't starting over with pulling data each time.
f = open(f_name+'.txt', 'wb')
conn, addr = s.accept()
while True:
data = conn.recv(1024)
if data != "":
f.write(data)
else:
return False
f.close()
print("File closed")
conn.close()

How to recieve files from a server in python?

I Have made a python script, where you can send files to a remote server and receive them. I can send them to the server but can not seem to retrieve them back I've attached both server and client.py
Server.py
import socket # Import socket module
import os
s = socket.socket()
s.bind(('139.59.173.187', 8010)) # Binds port and IP address
s.listen(3) #wait for client to join
c, addr = s.accept()
def RecvFile():
print ("File is comming ....")
file = c.recv(1024) #recieves file name from client
print(file)
f = open(file,'wb') #open that file or create one
l = c.recv(4096) #now recieves the contents of the file
while (l):
print ("Receiving...File Data")
f.write(l) #save input to file
l = c.recv(4096) #get again until done
print("The file",file,"has been succesfully saved to the server\nConnection from:",addr)
f.close()
def SendFile():
file = c.recv(1024)
print(file)
with open(file,'rb') as f:
c.sendall(f.read())
print("File has been sent to the client:", addr)
main()
def main():
option = str(c.recv(1024), 'utf-8')
print(option)
if option[:1] == "R":
SendFile()
elif option[:2] == "S":
RecvFile()
main()
s.close()
Client.py
import time
import socket
import sys
import urllib.request
#import paramiko
def login():
a = 1
while a == 1:
global user
user = input("Username:")
passw = input("Password:")
with open('User.txt') as f:
for line in f.readlines():
us, pw = line.strip().split("|", 1)
if (user == us) and (passw == pw):
print("login Successful!")
a = a+1
main()
return
print("Incorrect details, Try again!")
def register():
print("You will recieve a generated Username from your Name and age")
regName = input("First Name: ")
regAge = input("Age: ")
regPass = input("Password: ")
regUser = (regName[0:3]+regAge)
with open('User.txt', 'a') as file:
file.writelines(regUser+"|"+regPass+"\n")
print("You have Succesfully registered")
print("Your Username is:"+regUser)
print("Your Password is:"+regPass)
print("!Please keep these credentials secure!")
def main():
print("=========================Welcome to Bluetooth Projector=========================")
option = input("Here are your options:\n--> Press C to connect to the projector\n--> Press F for File System")
x = 1
while x == 1:
if option == "C" or option == "c":
optionc(x)
elif option == "F" or "f":
File_System()
def optionc():
print("Loading.....")
time.sleep(2)
print("Obtaining IP addres.....")
time.sleep(2)
print("Connecting.....")
time.sleep(3)
print("Connected")
x = x+1
def File_System():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('139.59.173.187',8010))
print("=========================Welcome to the File System =========================")
option = input("Here are your options:\n--> Press S to upload files\n--> Press R to retrieve files")
if option == "S" or option == "s":
s.send("S".encode('utf-8'))
file_name = input("Please input the file name\n>>>")
name = input("What would you like it to be saved as?\n>>>")
s.send(name.encode('utf-8'))
with open(file_name,'rb') as f:
s.sendall(f.read())
print("File has been sent to the server")
main()
elif option == "R" or option == "r":
s.send("R".encode('utf-8'))
filename = input("What is the filename you wish to recieve\n>>>")
s.send(filename.encode('utf-8'))
print ("File is comming ....")
f = open(filename,'wb') #open that file or create one
l = s.recv(1024) #now recieves the contents of the file
while (l):
print ("Receiving...File Data")
f.write(l) #save input to file
l = s.recv(1024)
print("The file",filename,"has been succesfully saved to your computer")
f.close()
while True:
check = input("Do you already have an account? Y/N \n ")
if check == "Y" or check == "y":
login()
break
elif check == "N" or check == "n":
register()
break
else:
print("pleae enter either Y or N")
Please look at the Filesystem() in the client file. I think it is receiving the second wave of bytes when getting files that is the problem
an was error is either broken pipe which I fixed.
But now the actually receiving file loop doesn't go through and stops getting the file bytes. I believe this is my error. I am confused however since my code is pretty much identical to sending the file to the server which has no complications.
But now the actually receiving file loop doesn't go through and stops getting the file bytes. I believe this is my error.
You are right. The client gets no indication that there aren't more file contents to come, and thus keeps on waiting in recv forever. To rectify this, you can let the server shut down the connection when the file has been sent, or, if you want the connection to be kept, inform the client about when it has to stop receiving, e. g. by sending it the file length beforehand.

Resources