Downloading a file using TCP(Client/Server)? - python

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();

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.

Related

Python Socket file transfer without closing sockets [duplicate]

This question already has answers here:
sending multiple files in python
(1 answer)
download multiple subsequent files from one server with one TCP handshake
(1 answer)
Sending multiple images with socket
(1 answer)
Sending multiple files through a TCP socket
(2 answers)
Closed last year.
I've been trying to transfer large files through python sockets, I can do it but it only works well if I close the connection, I want to keep the connection open and keep transfering files after that
Server:
import socket
import sys
from tqdm import tqdm
IP =
PORT =
ADDR = (IP, PORT)
SIZE = 4096
FORMAT = "utf-8"
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(ADDR)
server.listen()
print("[+] Listening...")
conn, addr = server.accept()
print(f"[+] Client connected from {addr[0]}:{addr[1]}")
#last try:
def receiver():
file_name = conn.recv(1024).decode()
file_size = conn.recv(1024).decode()
with open(file_name, "wb") as file:
c = 0
while c <= int(file_size):
data = conn.recv(1024)
if not (data):
break
file.write(data)
c += len(data)
def execute_rem(command):
conn.send(command.encode(FORMAT))
if command[0] == "exit":
conn.close()
server.close()
exit()
def run():
while True:
command = input(">> ")
if len(command) != 0:
conn.send(command.encode(FORMAT))
command = command.split(" ")
if command[0] == "download" and len(command) == 2:
receiver()
else:
result = conn.recv(SIZE)
if result == "1":
continue
else:
print(str(result, FORMAT))
run()
client:
import os
import sys
import socket
import time
import subprocess
from tqdm import tqdm
IP =
PORT =
ADDR = (IP, PORT)
SIZE = 4096
FORMAT = "utf-8"
WAITTIME = 10
client = 0
while True:
try:
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(ADDR)
break
except socket.error:
time.sleep(WAITTIME)
def exec_comnd(command):
cmd = subprocess.Popen(command,shell = True, stderr = subprocess.PIPE, stdout = subprocess.PIPE, stdin = subprocess.PIPE)
byte = cmd.stdout.read()+cmd.stderr.read()
if len(byte) == 0:
byte = "1"
return byte
def f_send(file_name):
file_size = os.path.getsize(file_name)
client.send(file_name.encode())
client.send(str(file_size).encode())
with open(file_name, "rb") as file:
c = 0
while c <= file_size:
data = file.read(1024)
if not (data):
break
client.sendall(data)
c += len(data)
def run():
while True:
command = client.recv(SIZE).decode(FORMAT)
command = command.split(" ")
if command[0] == "exit":
client.close()
exit()
elif command[0] == "cd" and len(command) == 2:
path = command[1]
os.chdir(path)
client.send(("Cambio a directorio " + path).encode(FORMAT))
elif command[0] == "download" and len(command) == 2:
f_send(command[1])
else:
res_comnd = exec_comnd(command)
client.send(res_comnd)
run()
This is my last attempt but I have tried different ways. The file gets sent but the server gets stuck until I ctl+c, after that, based on the output, server gets stuck on "data = conn.recv(1024))" (terminal output stops at "download test.jpg") and client gets stuck on "client.send(res_comnd)". I don't see why, is the only way closing the socket after the file transfer?
server output:
[+] Listening... [+] Client connected from
IP:PORT
>> download test.jpg
^CTraceback (most recent call last): File "/home/xxxx/project/nuev/server.py", line 94, in <module>
run() File "/home/xxxx/project/nuev/server.py", line 84, in run
receiver() File "/home/xxxx/project/nuev/server.py", line 36, in receiver
data = conn.recv(1024) KeyboardInterrupt
client output:
Traceback (most recent call last): File "C:\Users\xxxx\Desktop\client.py", line 108, in <module>
run() File "C:\Users\xxxx\Desktop\client.py", line 105, in run
client.send(res_comnd) ConnectionAbortedError: [WinError 10053] An established connection was aborted by the software in your host machine

How to transfer a file through a socket with Tkinter GUI(Python)

I have a client that let user to browse a file and upload to a server. Currently I'm just using command terminal to operate the program. When user type in fup in the terminal , the program will ask for filename and the file will be upload to the server if the filename input by user is valid.
So, what i want now is letting user to browse any file directory from a GUI without typing the filename to upload. I've tried to implement filedialog but it seem like not working, when i browse and upload a file, the server does not received any new file. I stucked with issues almost a week already but still couldn't find any solution, hope someone could help me. Thanks in advance
Client.py
import socket, sys, os
import time, shutil
# socket creating
def sock():
try:
s = socket.socket()
host = input('Enter Target IP :')
port = 9999
s.connect((host, port))
return (host, s)
except:
print("Error: In binding")
sock()
host, s = sock()
# upload file to client
def fup(conn):
try:
filename = input("\nMANO >>Filename? -> ")
if os.path.isfile(filename):
conn.send(str("fup~" + filename).encode("utf-8"))
conn.send(str.encode("EXISTS " + str(os.path.getsize(filename))))
filesize = int(os.path.getsize(filename))
userResponse = conn.recv(1024).decode("utf-8")
if userResponse[:2] == 'OK':
with open(filename, 'rb') as f:
bytesToSend = f.read(1024)
conn.send(bytesToSend)
totalSend = len(bytesToSend)
while int(totalSend) < int(filesize):
bytesToSend = f.read(1024)
totalSend += len(bytesToSend)
conn.send(bytesToSend)
sys.stdout.write("\r|" + "█" * int((totalSend / float(filesize)) * 50) + "|{0:.2f}".format(
(totalSend / float(filesize)) * 100) + "% ")
sys.stdout.flush()
print("\nUpload Completed!")
else:
print("File Does Not Exist!")
except:
print("Error")
# download file from client
def fdown(conn):
try:
print(os.getcwd())
filename = input("\nMANO >>Filename? -> ")
if filename != 'q':
conn.send(("fdown~" + filename).encode("utf-8"))
data = conn.recv(1024).decode("utf-8")
if data[:6] == 'EXISTS':
filesize = data[6:]
msg = input("File exists, " + str(filesize) + "Bytes, download? (Y/N)? -> ").upper()
if msg == 'Y':
conn.send("OK".encode("utf-8"))
f = open(filename, 'wb')
data = (conn.recv(1024))
totalRecv = len(data)
f.write(data)
while int(totalRecv) < int(filesize):
data = conn.recv(1024)
totalRecv += len(data)
f.write(data)
sys.stdout.write("\r|" + "█" * int((totalRecv / float(filesize)) * 50) + "|{0:.2f}".format(
(totalRecv / float(filesize)) * 100) + "% ")
sys.stdout.flush()
time.sleep(0.01)
print("\nDownload Complete!")
f.close()
else:
print("File Does Not Exist!")
except:
print("Error")
# commands that perform on client
def mano(cip, conn):
while True:
cli = input("MANO >>" + cip + ' >>')
if cli == 'fdown':
fdown(conn)
elif cli == 'fup':
fup(conn)
else:
print("Command not recognized")
mano(host, s)
Server.py
import socket, os, subprocess, shutil, pickle, struct, threading
## gettig the hostname by socket.gethostname() method
hostname = socket.gethostname()
## getting the IP address using socket.gethostbyname() method
ip_address = socket.gethostbyname(hostname)
# Create a Socket ( connect two computers)
def create_socket():
try:
global host
global port
global s
host = ""
port = 9999
s = socket.socket()
except socket.error as msg:
create_socket()
# Binding the socket and listening for connections
def bind_socket():
try:
global host
global port
global s
s.bind((host, port))
s.listen(5)
## printing the hostname and ip_address
print(f"Hostname: {hostname}")
print(f"IP Address: {ip_address}")
print(f"Running Port: {port}")
except socket.error as msg:
bind_socket()
print(bind_socket())
# send file list
def flist(conn):
try:
arr = pickle.dumps(os.listdir())
conn.send(arr)
print(arr)
except:
conn.send(('Error').encode("utf-8"))
# accept file from server
def fdown(filename, conn):
try:
data = conn.recv(1024).decode("utf-8")
if data[:6] == 'EXISTS':
filesize = data[6:]
conn.send("OK".encode("utf-8"))
f = open(filename, 'wb')
data = (conn.recv(1024))
totalRecv = len(data)
f.write(data)
while int(totalRecv) < int(filesize):
data = conn.recv(1024)
totalRecv += len(data)
f.write(data)
f.close()
except:
conn.send(('Error').encode("utf-8"))
# send file
def fup(filename, conn):
if os.path.isfile(filename):
conn.send(str.encode("EXISTS " + str(os.path.getsize(filename))))
filesize = int(os.path.getsize(filename))
userResponse = conn.recv(1024).decode("utf-8")
if userResponse[:2] == 'OK':
with open(filename, 'rb') as f:
bytesToSend = f.read(1024)
conn.send(bytesToSend)
totalSend = len(bytesToSend)
while int(totalSend) < int(filesize):
bytesToSend = f.read(1024)
totalSend += len(bytesToSend)
conn.send(bytesToSend)
else:
conn.send("ERROR".encode("utf-8"))
# main
def main(s):
while True:
data = (s.recv(1024)).decode("utf-8").split('~')
if data[0] == 'fdown':
fup(data[1], s)
elif data[0] == 'fup':
fdown(data[1], s)
elif data[0] == 'flist':
flist(s)
else:
s.send(".".encode('utf-8'))
def socket_accept():
while True:
conn, address = s.accept()
t = threading.Thread(target=main, args=(conn,))
t.start()
create_socket()
bind_socket()
socket_accept()
Expected output:
since you are using a gui I think you should receive the inputs through the use of an tkinter.Entry widget not through the terminal with input()

OSError: [Errno 9] Bad file descriptor

I initially tried using python to run but there were different errors so I tried using python3 and received the error in the title. I am trying to connect to server and download a file that has tls implemented.
import socket, ssl, pprint
import os, time
import threading
def main():
s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = ssl.wrap_socket(s2,
server_side = False,
ca_certs="CA.crt",
cert_reqs=ssl.CERT_REQUIRED)
s2.connect(('localhost',10024))
filename = raw_input("What file do you wish to download? -> ")
if filename != 'q':
s2.send(filename)
data = s2.recv(1024)
if data [:7] == 'fEXISTS':
fSize = long(data[7:])
message = raw_input("The file you wish to download is " +str(fSize)+\
"bytes, would you like to proceed? (y/n): ")
if message == 'y':
s2.send ('OK')
f = open('new_'+filename, 'wb')
data = s2.recv(2000000)
totalRecv = len(data)
f.write(data)
while totalRecv < fSize:
data = s2.recv(2000000)
totalRecv += len(data)
f.write(data)
progress = ((totalRecv/float(fSize))*100)
print ("{0: .2F}".format(progress)+\
"% Completed")
else:
print ("ERROR: File does not exist!")
s2.close()
if __name__ == '__main__':
main()
After wrapping the socket in an SSL context (with ssl.wrap_socket), you should not be using the original socket anymore.
You should be calling connect, send, recv, etc. on ssl_sock, not on s2.
(Specifically, when you call ssl.wrap_socket, the .detach method is called on the original socket which removes the file descriptor from it. The file descriptor is transferred to the SSL socket instance. The only thing you can do with the original then is close/destroy it.)

Napster-style peer-to-peer (P2P) file sharing system using rpyc and message-orianted(Python)

I have a task in which I should make Napster-style peer-to-peer (P2P) file sharing system. I used rpyc and message-oriented at the same time, but I have a problem when I download a file from other peer - the code just runs infinite and never stops, no output.
Peer has two classes Client and server
from socket import *
import socket
import os
import pickle
import rpyc
from rpyc.utils.server import ThreadedServer
from const import *
class Client():
conn = rpyc.connect(HOST, PORT) # Connect to the index_server
def lookUp(self,filename):
PeerList = self.conn.root.exposed_search(filename)
if PeerList==False:
print "no File with this Name"
else:
print PeerList
def register_on_server(self,Filename,port):
self.conn.root.exposed_register(Filename,port)
def download(self, serverhost, serverport, filename): # function download a file from another peer
sock.connect((serverhost,serverport))
print("Client Connected to download a file")
sock.send(pickle.dumps(filename))
localpath = "C:\Users\aa\PycharmProjects\task1\downloadfiles"
data = sock.recv(1024)
totalRecv = len(data)
f = open(localpath + '/' + filename, 'wb')
f.write(data)
filesize = os.path.getsize('C:\Users\aa\PycharmProjects\task1\uploadfiles' + '/' + filename)
while totalRecv < filesize:
data = sock.recv(1024)
totalRecv += len(data)
f.write(data)
print("File is downloaded Successfully")
sock.close()
class Server(rpyc.Service):
def __init__(self, host, port):
self.host = host
self.port = port # the port it will listen to
global sock
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # socket for incoming calls
sock.bind((self.host, self.port)) # bind socket to an address
sock.listen(5) # max num connections
def obtain(self):
remotepath = "C:\Users\aa\PycharmProjects\task1\uploadfiles"
while True:
client, address = sock.accept()
print("Client Connected to download a file")
try:
filename = client.recv(1024)
if os.path.exists(remotepath + '/' + filename):
filesize = os.path.getsize(remotepath + '/' + filename)
if filesize > 0:
client.send(str(filesize))
with open(remotepath + '/' + filename, 'rb') as f:
bytes = f.read(1024)
client.send(bytes)
while bytes != "":
bytes = f.read(1024)
client.send(bytes)
else:
client.send("Empty")
else:
client.send("False")
except:
client.close()
return False
if __name__ == "__Server__":
server = ThreadedServer(Server, hostname=Server.host, port=Server.port)
server.start()
{Peer2}
from time import sleep
import rpyc
from peer import *
from const import *
peer2 = Client()
print ('1-register')
print ('2-search')
print ('3-download')
while(True):
commend = raw_input("enter your commend")
if commend == 'register':
filename = raw_input("write the file name")
peer2.register_on_server(filename,PeeR2PORT)
elif commend == 'search':
filename = raw_input("write the file name")
peer2.lookUp(filename)
elif commend == 'download':
port = raw_input("enter the other peer port")
host = raw_input("enter the other peer host")
filename = raw_input("enter the file name")
peer1 = Server(PeeR1HOST, PeeR1PORT)
peer1.obtain()
peer2.download(host, port, filename)
You create a call to peer1.obtain() which runs the peer to accept calls from different peers to download the file. However, you try to call peer1.download() from the same peer while it is already listening for incoming calls. You need to separate peer1.download() to run from different peer.
You need to revise how Napster FileSharing System works.
We are not here to solve your assignment. You seem to have good knowledge with python, the issue is that you do not understand the task good enough. We can help you with understanding its concept, helping you with syntax errors,..,etc.

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