master
Eric 7 months ago
commit ebb7ed59fc

@ -0,0 +1,357 @@
import tkinter as tk
from tkinter import ttk, filedialog
import os
import socket
import threading
import time
class FTPClient:
def __init__(self):
self.server_dir = ""
self.root = tk.Tk()
self.root.title("Cliente de Archivos")
self.root.geometry("950x600")
# Valores predeterminados para la dirección IP y el puerto
default_ip = "127.0.0.1"
default_port = "12345"
# Frame para la conexión
self.connection_frame = tk.Frame(self.root)
self.connection_frame.pack(pady=10)
self.con_frame = tk.LabelFrame(self.connection_frame, text="Conexion")
self.con_frame.grid(row=0, column=0, padx=10, pady=5)
self.label_ip = tk.Label(self.con_frame, text="IP del Servidor:")
self.label_ip.grid(row=0, column=0, padx=5)
self.entry_ip = tk.Entry(self.con_frame, width=20)
self.entry_ip.insert(0, default_ip)
self.entry_ip.grid(row=0, column=1, padx=5)
self.label_port = tk.Label(self.con_frame, text="Puerto:")
self.label_port.grid(row=0, column=2, padx=5)
self.entry_port = tk.Entry(self.con_frame, width=10)
self.entry_port.insert(0, default_port)
self.entry_port.grid(row=0, column=3, padx=5)
self.button_connect = tk.Button(self.con_frame, text="Conectar", width=10, command=self.connect_to_server)
self.button_connect.grid(row=0, column=4, padx=5)
self.button_disconnect = tk.Button(self.con_frame, text="Desconectar", width=10, state=tk.DISABLED, command=self.disconnect_from_server)
self.button_disconnect.grid(row=0, column=5, padx=5)
# Frame principal para los archivos locales y directorios del servidor
self.main_frame = tk.Frame(self.root)
self.main_frame.pack(fill="both", expand=True, padx=20, pady=5)
# Frame para la configuración de la carpeta local del cliente
self.config_frame = tk.LabelFrame(self.main_frame, text="Configuración de Carpeta Local")
self.config_frame.pack(fill="x", expand=True, padx=20, pady=5, anchor="center") # Alinear al centro
self.label_local_folder = tk.Label(self.config_frame, text="Carpeta Local:")
self.label_local_folder.grid(row=0, column=0, padx=20, sticky="e")
self.entry_local_folder = tk.Entry(self.config_frame, width=50)
self.entry_local_folder.grid(row=0, column=1, padx=20, sticky="w")
self.button_browse = tk.Button(self.config_frame, text="Explorar", width=10, command=self.browse_local_folder)
self.button_browse.grid(row=0, column=2, padx=20, pady=10, sticky="e")
self.button_apply = tk.Button(self.config_frame, text="Aplicar", width=10, command=self.apply_local_folder)
self.button_apply.grid(row=0, column=3, padx=5, pady=10, sticky="w")
# Frame para los botones de navegación de archivos locales
self.local_nav_frame = tk.Frame(self.main_frame)
self.local_nav_frame.pack(side="left", padx=5)
self.button_up = tk.Button(self.local_nav_frame, text="Subir", command=self.go_up)
self.button_up.pack(side="top", pady=5)
self.button_open = tk.Button(self.local_nav_frame, text="Abrir", command=self.open_directory)
self.button_open.pack(side="top", pady=5)
# Frame para los botones de navegación de archivos del servidor
self.server_nav_frame = tk.Frame(self.main_frame)
self.server_nav_frame.pack(side="right", padx=5)
self.server_button_up = tk.Button(self.server_nav_frame, text="Subir", command=self.go_up_server)
self.server_button_up.pack(side="top", pady=5)
self.server_button_open = tk.Button(self.server_nav_frame, text="Abrir", command=self.open_directory_server)
self.server_button_open.pack(side="top", pady=5)
# Frame para todos los archivos
self.files_frame = tk.Frame(self.main_frame)
self.files_frame.pack(fill="both", expand=True, padx=20, pady=5)
# Frame para los archivos locales
self.local_files_frame = tk.LabelFrame(self.files_frame, text="Archivos Locales")
self.local_files_frame.pack(side="left", fill="both", expand=True)
self.local_files_list = tk.Listbox(self.local_files_frame, width=50, height=20)
self.local_files_list.pack(side="left", fill="both", expand=True)
self.local_files_scrollbar = ttk.Scrollbar(self.local_files_frame, orient="vertical")
self.local_files_scrollbar.config(command=self.local_files_list.yview)
self.local_files_scrollbar.pack(side="right", fill="y")
self.local_files_list.config(yscrollcommand=self.local_files_scrollbar.set)
# Frame para los archivos del servidor
self.server_files_frame = tk.LabelFrame(self.files_frame, text="Archivos del Servidor")
self.server_files_frame.pack(side="right", fill="both", expand=True)
self.server_files_list = tk.Listbox(self.server_files_frame, width=50, height=20)
self.server_files_list.pack(side="left", fill="both", expand=True)
self.server_files_scrollbar = ttk.Scrollbar(self.server_files_frame, orient="vertical")
self.server_files_scrollbar.config(command=self.server_files_list.yview)
self.server_files_scrollbar.pack(side="right", fill="y")
self.server_files_list.config(yscrollcommand=self.server_files_scrollbar.set)
# Frame para el botón y la ProgressBar
self.upload_frame = tk.Frame(self.main_frame)
self.upload_frame.pack(side="left", fill="both", pady=10)
self.button_send_file = tk.Button(self.upload_frame, text="Enviar Archivo", command=self.send_selected_file)
self.button_send_file.pack(side="left", padx=10)
self.entry_server_path = tk.Entry(self.upload_frame, width=50)
self.entry_server_path.pack(side="left", pady=5)
self.progress_bar = ttk.Progressbar(self.upload_frame, orient="horizontal", length=200, mode="determinate")
self.progress_bar.pack(side="right", padx=10)
self.timer_label = tk.Label(self.upload_frame, text="")
self.timer_label.pack()
self.client_socket = None
self.monitor_thread = None # Hilo para monitorear el buzón de entrada
def connect_to_server(self):
server = self.entry_ip.get()
port = int(self.entry_port.get())
self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
print("Conectando al servidor...")
self.client_socket.settimeout(10) # Establecer un tiempo de espera de 10 segundos para la respuesta del servidor
self.client_socket.connect((server, port))
credentials = "user:password"
self.client_socket.send(credentials.encode())
print(f"Conectado al servidor {server}:{port}")
# Esperar y recibir el mensaje de bienvenida del servidor
response = self.receive_response(self.client_socket)
print("Mensaje de bienvenida del servidor:", response.decode("utf-8"))
# Si el mensaje indica que el servidor está listo, continuar con la configuración
if response.startswith(b"pyftpdlib"):
# Enviar comando para obtener el directorio del servidor
self.send_data(b"PWD", self.client_socket)
server_dir_response = self.receive_response(self.client_socket)
print("Respuesta del servidor al solicitar el directorio:", server_dir_response.decode("utf-8"))
default_server_dir = server_dir_response.decode("utf-8").split('"')[1] # Extraer el directorio del servidor de la respuesta
print(f"Directorio predeterminado del servidor: {default_server_dir}")
self.update_default_server_dir(default_server_dir) # Actualizar la interfaz con el directorio predeterminado del servidor
# Restaurar el tiempo de espera del socket a 5 segundos
self.client_socket.settimeout(5)
self.button_connect.config(state=tk.DISABLED)
self.button_disconnect.config(state=tk.NORMAL)
self.monitor_thread = threading.Thread(target=self.monitor_inbox)
self.monitor_thread.start() # Iniciar el hilo de monitoreo del buzón de entrada
else:
print("Respuesta inesperada del servidor:", response.decode("utf-8"))
except socket.timeout:
print("Conexión agotada. Por favor, verifique la IP y el puerto del servidor.")
except Exception as e:
print(f"Error al conectar al servidor: {e}")
def disconnect_from_server(self):
if self.client_socket:
self.client_socket.close()
print("Disconnected from server.")
self.button_connect.config(state=tk.NORMAL)
self.button_disconnect.config(state=tk.DISABLED)
def send_selected_file(self):
selected_file = self.local_files_list.get(tk.ACTIVE)
full_path = os.path.join(self.entry_local_folder.get(), selected_file)
if os.path.isfile(full_path):
recipient = "" # Introduce el destinatario si es necesario
threading.Thread(target=self.upload_file, args=(full_path, recipient)).start() # Ejecutar la función de carga en un hilo separado
else:
print("Please select a file to send.")
def upload_file(self, filename, recipient):
try:
with open(filename, 'rb') as file:
self.send_data(b'SEND_FILE', self.client_socket)
self.send_data(recipient.encode('utf-8'), self.client_socket)
self.send_file(filename, self.client_socket)
print(f"File '{filename}' uploaded successfully to {recipient}")
except Exception as e:
print(f"Error uploading file: {e}")
def send_file(self, filename, client_socket):
with open(filename, 'rb') as file:
filename_bytes = os.path.basename(filename).encode('utf-8')
self.send_data(filename_bytes, client_socket)
file_size = os.path.getsize(filename)
self.send_data(str(file_size).encode('utf-8'), client_socket)
sent_bytes = 0
while True:
chunk = file.read(1024)
if not chunk:
break
client_socket.sendall(chunk)
sent_bytes += len(chunk)
# Actualizar la ProgressBar
progress = min(int(sent_bytes / file_size * 100), 100)
self.progress_bar['value'] = progress
self.root.update_idletasks() # Actualizar la interfaz gráfica
def monitor_inbox(self):
while True:
self.send_data(b'CHECK_INBOX', self.client_socket)
data = self.receive_response(self.client_socket)
if data:
filename = data.decode('utf-8')
self.receive_file(filename)
time.sleep(300) # Check every 5 minutes
def receive_file(self, filename):
try:
with open(filename, 'wb') as file:
filename_bytes = filename.encode('utf-8')
self.send_data(b'RETRIEVE_FILE', self.client_socket)
self.send_data(filename_bytes, self.client_socket)
file_size = int(self.receive_response(self.client_socket).decode('utf-8'))
received_bytes = 0
while received_bytes < file_size:
chunk = self.client_socket.recv(1024)
if not chunk:
break
file.write(chunk)
received_bytes += len(chunk)
print(f"File '{filename}' downloaded successfully")
except Exception as e:
print(f"Error receiving file: {e}")
def receive_response(self, client_socket):
try:
print("Esperando respuesta del servidor...")
response_data = b'' # Inicializar un buffer para almacenar los datos recibidos
# Recibir los datos hasta que se encuentre el delimitador especial
while True:
chunk = client_socket.recv(1024)
if not chunk:
break
response_data += chunk
if b'\n' in chunk:
break
response_str = response_data # Devolver los datos recibidos tal cual
print(f"Respuesta del servidor recibida: {response_str}")
return response_str
except Exception as e:
print(f"Error al recibir respuesta del servidor: {e}")
return None
def send_data(self, data, client_socket):
data_size = len(data)
data_size_bytes = data_size.to_bytes(4, byteorder='big')
client_socket.sendall(data_size_bytes)
total_sent = 0
while total_sent < data_size:
sent = client_socket.send(data[total_sent:])
if sent == 0:
raise RuntimeError("Connection closed unexpectedly.")
total_sent += sent
def browse_local_folder(self):
folder_path = filedialog.askdirectory()
self.entry_local_folder.delete(0, tk.END)
self.entry_local_folder.insert(0, folder_path)
self.update_local_files_list()
def apply_local_folder(self):
folder_path = self.entry_local_folder.get()
if os.path.isdir(folder_path):
self.update_local_files_list()
else:
print("Invalid directory path.")
def go_up(self):
current_path = self.entry_local_folder.get()
parent_path = os.path.dirname(current_path)
if os.path.isdir(parent_path):
self.entry_local_folder.delete(0, tk.END)
self.entry_local_folder.insert(0, parent_path)
self.update_local_files_list()
def open_directory(self):
selected_path = self.local_files_list.get(tk.ACTIVE)
full_path = os.path.join(self.entry_local_folder.get(), selected_path)
if os.path.isdir(full_path):
self.entry_local_folder.delete(0, tk.END)
self.entry_local_folder.insert(0, full_path)
self.update_local_files_list()
def go_up_server(self):
current_path = self.entry_server_folder.get()
parent_path = os.path.dirname(current_path)
if parent_path:
self.entry_server_folder.delete(0, tk.END)
self.entry_server_folder.insert(0, parent_path)
self.update_server_files_list()
def open_directory_server(self):
selected_path = self.server_files_list.get(tk.ACTIVE)
full_path = os.path.join(self.entry_server_folder.get(), selected_path)
if os.path.isdir(full_path):
self.entry_server_folder.delete(0, tk.END)
self.entry_server_folder.insert(0, full_path)
self.update_server_files_list()
def update_local_files_list(self):
folder_path = self.entry_local_folder.get()
self.local_files_list.delete(0, tk.END)
if os.path.isdir(folder_path):
files = os.listdir(folder_path)
for file in files:
self.local_files_list.insert(tk.END, file)
def update_default_server_dir(self, directory):
# Actualizar el atributo del directorio del servidor
self.server_dir = directory
# Limpiar la lista de archivos del servidor
self.server_files_list.delete(0, tk.END)
# Obtener la lista de archivos en el nuevo directorio del servidor
self.send_data(b'LIST_FILES', self.client_socket)
self.send_data(directory.encode('utf-8'), self.client_socket)
files_data = self.receive_response(self.client_socket)
# Decodificar los datos recibidos y agregar cada archivo a la lista
files = files_data.decode('utf-8').split('\n')
for file in files:
self.server_files_list.insert(tk.END, file)
def run(self):
self.root.mainloop()
def main():
client = FTPClient()
client.run()
if __name__ == "__main__":
main()

@ -0,0 +1,49 @@
# Cliente y Servidor de Envío de Archivos
Este proyecto consiste en una aplicación cliente-servidor desarrollada en Python que permite a los usuarios enviar archivos de un cliente a un servidor.
## Cliente
El cliente de la aplicación está diseñado con una interfaz gráfica simple usando la biblioteca Tkinter de Python. Permite al usuario conectarse al servidor, explorar archivos locales y enviar archivos seleccionados al servidor.
### Características del Cliente:
- **Conexión al Servidor:** El cliente puede conectarse al servidor proporcionando la dirección IP y el puerto.
- **Exploración de Archivos Locales:** Se puede navegar a través de los archivos locales del cliente para seleccionar un archivo para enviar al servidor.
- **Envío de Archivos:** Una vez que se selecciona un archivo, el cliente puede enviarlo al servidor. Muestra el progreso del envío con una barra de progreso.
### Requisitos del Cliente:
- Python 3.x instalado.
- Biblioteca Tkinter (normalmente incluida con la instalación estándar de Python).
## Servidor
El servidor es una aplicación de consola simple que espera conexiones de clientes. Cuando un cliente se conecta, el servidor recibe el archivo enviado por el cliente y lo guarda en una carpeta designada.
### Características del Servidor:
- **Espera de Conexiones:** El servidor espera a que los clientes se conecten en un puerto especificado.
- **Recepción de Archivos:** Cuando un cliente se conecta y envía un archivo, el servidor lo recibe y lo guarda en la carpeta designada.
- **Creación de Carpetas de Usuario:** Si la carpeta de usuario correspondiente no existe en el servidor, el servidor la crea automáticamente al recibir la primera conexión de ese usuario.
### Requisitos del Servidor:
- Python 3.x instalado.
## Uso
### Cliente:
1. Ejecute el script `Cliente.py`.
2. Ingrese la dirección IP y el puerto del servidor al que desea conectarse.
3. Haga clic en el botón "Conectar".
4. Use el botón "Buscar Archivos" para explorar los archivos locales y seleccione el archivo que desea enviar.
5. Haga clic en el botón "Enviar Archivo" para enviar el archivo seleccionado al servidor.
### Servidor:
1. Ejecute el script `Servidor.py`.
2. El servidor comenzará a esperar conexiones de clientes en el puerto especificado.
3. Los archivos enviados por los clientes se guardarán en la carpeta `usuarios` en el servidor, en una subcarpeta correspondiente al cliente.
## Notas Adicionales
- Asegúrese de que el cliente y el servidor estén en la misma red para que puedan comunicarse correctamente.
- Siempre verifique las configuraciones de firewall y permisos de red para permitir la comunicación entre el cliente y el servidor.

@ -0,0 +1,72 @@
from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer
import os
import time
import string
class CustomFTPHandler(FTPHandler):
def on_connect(self):
super().on_connect()
self.username = "user"
print("Cliente conectado.")
def on_login(self, username):
super().on_login(username)
self.username = username
self.user_dir = os.path.join(self.authorizer.get_home_dir(username), 'inbox')
# Send the default server directory path to the client
default_server_dir = "/home/eric/ProyectoJuanjoSegundoTrimestre/usuario" # Cambiar esto al directorio predeterminado
self.send_response("DEFAULT_DIR", default_server_dir)
print(f"Directorio predeterminado del servidor enviado al cliente: {default_server_dir}")
def send_response(self, code, message):
resp = f"{code} {message}\r\n"
self.push(resp)
def on_file_sent(self, file):
super().on_file_sent(file)
self.broadcast_file_sent(os.path.basename(file))
def broadcast_file_sent(self, filename):
print(f"File '{filename}' sent")
def list_files_in_user_inbox(self):
files = []
try:
files = os.listdir(self.user_dir)
except FileNotFoundError:
pass
return files
def normalize_filename(self, filename):
valid_chars = "-_.() %s%s" % (string.ascii_letters, string.digits)
filename = ''.join(c for c in filename if c in valid_chars)
filename = filename[:255] # Limit filename length to 255 characters
return filename
def save_file(self, filename, data):
try:
filename = self.normalize_filename(filename)
with open(os.path.join(self.user_dir, filename), 'wb') as file:
file.write(data)
print(f"File '{filename}' saved to {self.username}'s inbox.")
except Exception as e:
print(f"Error saving file: {e}")
def run_ftp_server():
authorizer = DummyAuthorizer()
# Creamos un único usuario
authorizer.add_user("user", "password", "/home/eric/ProyectoJuanjoSegundoTrimestre/usuario", perm="lradw") # Cambia "/path/to/home/directory" al directorio que desees
handler = CustomFTPHandler
handler.authorizer = authorizer
server = FTPServer(("127.0.0.1", 12345), handler)
server.max_cons_per_ip = 5
server.serve_forever()
if __name__ == "__main__":
run_ftp_server()
Loading…
Cancel
Save

Powered by INFORMATICA.FP.EDU.ES.