Primera rendición interfaz de usuario
parent
23b319fe2a
commit
beb8abc88a
|
|
@ -0,0 +1,202 @@
|
|||
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()
|
||||
Loading…
Reference in New Issue