import socket import threading import tkinter as tk from tkinter import ttk, filedialog, messagebox import os # ========================================== # CONFIGURACIÓN # ========================================== def obtener_ip_local(): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: s.connect(("8.8.8.8", 80)) ip = s.getsockname()[0] except: ip = "127.0.0.1" finally: s.close() return ip PUERTO = 5000 IP_LOCAL = obtener_ip_local() # ========================================== # SERVIDOR # ========================================== def servidor_archivos(): if not os.path.exists("recibidos"): os.makedirs("recibidos") srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) srv.bind(("0.0.0.0", PUERTO)) srv.listen(5) print(f"[SERVIDOR] Escuchando en {IP_LOCAL}:{PUERTO}") while True: client, addr = srv.accept() print(f"[SERVIDOR] Conexión desde {addr}") info = client.recv(1024).decode() nombre, tamaño = info.split("|") tamaño = int(tamaño) with open(f"recibidos/{nombre}", "wb") as f: recibido = 0 while recibido < tamaño: datos = client.recv(4096) if not datos: break f.write(datos) recibido += len(datos) client.send("Archivo recibido correctamente".encode()) client.close() threading.Thread(target=servidor_archivos, daemon=True).start() # ========================================== # APLICACIÓN GUI # ========================================== class App: def __init__(self, root): self.root = root self.root.title("Enviador de Archivos") self.root.geometry("450x320") self.crear_pantalla_principal() # ------------------------- # PANTALLA PRINCIPAL # ------------------------- def crear_pantalla_principal(self): self.limpiar_ventana() tk.Label(self.root, text="Enviador de archivos", font=("Arial", 18)).pack(pady=10) tk.Label(self.root, text=f"Tu IP: {IP_LOCAL}", font=("Arial", 12)).pack(pady=5) tk.Button(self.root, text="Buscar equipos", font=("Arial", 14), command=self.buscar_equipos).pack(pady=20) self.lista = tk.Listbox(self.root, width=40, height=6) self.lista.pack() tk.Button(self.root, text="Enviar archivo al equipo seleccionado", command=self.ir_a_seleccionar_archivo).pack(pady=10) # ------------------------- # BUSCAR EQUIPOS # ------------------------- def buscar_equipos(self): self.lista.delete(0, tk.END) base = IP_LOCAL.rsplit(".", 1)[0] for i in range(1, 255): ip_objetivo = f"{base}.{i}" threading.Thread(target=self.comprobar_equipo, args=(ip_objetivo,), daemon=True).start() def comprobar_equipo(self, ip): s = socket.socket() s.settimeout(0.3) try: s.connect((ip, PUERTO)) self.lista.insert(tk.END, ip) except: pass s.close() # ------------------------- # SELECCIONAR ARCHIVO # ------------------------- def ir_a_seleccionar_archivo(self): seleccionado = self.lista.curselection() if not seleccionado: messagebox.showwarning("Aviso", "Selecciona un equipo primero.") return self.ip_destino = self.lista.get(seleccionado[0]) self.crear_pantalla_seleccionar_archivo() def crear_pantalla_seleccionar_archivo(self): self.limpiar_ventana() tk.Label(self.root, text=f"Enviando a: {self.ip_destino}", font=("Arial", 14)).pack(pady=10) tk.Button(self.root, text="Seleccionar archivo", command=self.seleccionar_archivo).pack(pady=20) tk.Button(self.root, text="Volver", command=self.crear_pantalla_principal).pack(pady=10) def seleccionar_archivo(self): archivo = filedialog.askopenfilename() if archivo: self.enviar_archivo(archivo) # ------------------------- # ENVÍO DEL ARCHIVO # ------------------------- def enviar_archivo(self, ruta): nombre = os.path.basename(ruta) tamaño = os.path.getsize(ruta) try: s = socket.socket() s.connect((self.ip_destino, PUERTO)) s.send(f"{nombre}|{tamaño}".encode()) with open(ruta, "rb") as f: while True: datos = f.read(4096) if not datos: break s.send(datos) confirm = s.recv(1024).decode() s.close() self.pantalla_confirmacion(confirm) except Exception as e: messagebox.showerror("Error", f"No se pudo enviar el archivo:\n{e}") # ------------------------- # PANTALLA DE CONFIRMACIÓN # ------------------------- def pantalla_confirmacion(self, mensaje): self.limpiar_ventana() tk.Label(self.root, text="✔️ Archivo enviado", font=("Arial", 18)).pack(pady=20) tk.Label(self.root, text=mensaje, font=("Arial", 14)).pack(pady=10) tk.Button(self.root, text="Volver al inicio", command=self.crear_pantalla_principal, font=("Arial", 14)).pack(pady=20) # ------------------------- # UTILIDAD # ------------------------- def limpiar_ventana(self): for widget in self.root.winfo_children(): widget.destroy() # ========================================== # INICIAR APP # ========================================== root = tk.Tk() app = App(root) root.mainloop()