""" TRANSFERENCIA DE ARCHIVOS - SIN TUPLAS NI DICCIONARIOS Versión ultra simplificada para explicación """ # ======================================== # IMPORTS # ======================================== import socket import threading import tkinter as tk import os # ======================================== # VARIABLES GLOBALES # ======================================== MI_IP = "" PUERTO = 5000 BUFFER_TAMANO = 4096 ARCHIVO_A_ENVIAR = "" IP_DESTINO = "" # ======================================== # FUNCIONES DE RED # ======================================== def conseguir_mi_ip(): """Consigue la IP de esta computadora""" try: s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(("8.8.8.8", 80)) ip_numero = s.getsockname()[0] s.close() return ip_numero except: return "127.0.0.1" def escuchar_archivos(): """Escucha conexiones y recibe archivos""" # Crear carpeta para archivos recibidos if not os.path.exists("recibidos"): os.makedirs("recibidos") # Crear socket servidor servidor_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) servidor_socket.bind(("0.0.0.0", PUERTO)) servidor_socket.listen(5) print(f"Escuchando en puerto {PUERTO}...") while True: # Esperar conexión cliente_socket, direccion_cliente = servidor_socket.accept() ip_cliente = direccion_cliente[0] # Solo tomamos la IP (no el puerto) print(f"Conexión desde: {ip_cliente}") # Recibir información del archivo info_archivo = cliente_socket.recv(1024).decode() # Separar nombre y tamaño if "|" in info_archivo: partes = info_archivo.split("|") nombre_archivo = partes[0] tamaño_archivo = int(partes[1]) # Guardar archivo ruta_completa = "recibidos/" + nombre_archivo # Evitar sobrescribir archivos contador = 1 while os.path.exists(ruta_completa): nombre_base = nombre_archivo.split(".")[0] extension = nombre_archivo.split(".")[-1] ruta_completa = f"recibidos/{nombre_base}_{contador}.{extension}" contador += 1 # Abrir archivo para escribir archivo_destino = open(ruta_completa, "wb") # Recibir datos en partes bytes_recibidos = 0 while bytes_recibidos < tamaño_archivo: datos = cliente_socket.recv(BUFFER_TAMANO) archivo_destino.write(datos) bytes_recibidos += len(datos) # Cerrar archivo archivo_destino.close() print(f"Archivo guardado: {ruta_completa}") # Enviar confirmación cliente_socket.send(b"OK") # Cerrar conexión cliente_socket.close() def mandar_archivo(ruta, ip): """Envía un archivo a otra computadora""" # Verificar que el archivo existe if not os.path.exists(ruta): return False # Obtener información del archivo nombre_archivo = os.path.basename(ruta) tamaño_archivo = os.path.getsize(ruta) try: # Crear socket cliente cliente_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) cliente_socket.settimeout(10) # Conectar al destino cliente_socket.connect((ip, PUERTO)) # Enviar información del archivo mensaje_info = nombre_archivo + "|" + str(tamaño_archivo) cliente_socket.send(mensaje_info.encode()) # Abrir y enviar archivo archivo_origen = open(ruta, "rb") while True: datos = archivo_origen.read(BUFFER_TAMANO) if not datos: break cliente_socket.send(datos) # Cerrar archivo archivo_origen.close() # Esperar confirmación respuesta = cliente_socket.recv(1024) cliente_socket.close() if respuesta == b"OK": return True else: return False except Exception as error: print(f"Error: {error}") return False def buscar_computadoras(): """Busca otras computadoras en la red""" computadoras_encontradas = [] # Obtener base de IP partes_ip = MI_IP.split(".") if len(partes_ip) == 4: ip_base = partes_ip[0] + "." + partes_ip[1] + "." + partes_ip[2] # Probar primeras 20 IPs for ultimo_numero in range(1, 21): ip_completa = ip_base + "." + str(ultimo_numero) # Saltar nuestra propia IP if ip_completa == MI_IP: continue # Intentar conectar try: s = socket.socket() s.settimeout(0.2) s.connect((ip_completa, PUERTO)) computadoras_encontradas.append(ip_completa) s.close() except: pass return computadoras_encontradas # ======================================== # INTERFAZ GRÁFICA # ======================================== class AplicacionTransferencia: def __init__(self): # Crear ventana principal self.ventana_principal = tk.Tk() self.ventana_principal.title("Enviar Archivos") self.ventana_principal.geometry("400x450") # Variables de la aplicación global MI_IP MI_IP = conseguir_mi_ip() # Lista para equipos encontrados self.lista_equipos = [] # Crear interfaz self.crear_interfaz_grafica() # Iniciar servidor en segundo plano hilo_servidor = threading.Thread(target=escuchar_archivos) hilo_servidor.daemon = True hilo_servidor.start() def crear_interfaz_grafica(self): """Crea todos los elementos visuales""" # Título etiqueta_titulo = tk.Label(self.ventana_principal, text="Enviar Archivos", font=("Arial", 18)) etiqueta_titulo.pack(pady=20) # Mostrar IP local etiqueta_ip = tk.Label(self.ventana_principal, text="Tu IP: " + MI_IP, font=("Arial", 12)) etiqueta_ip.pack(pady=10) # Línea separadora linea = tk.Frame(self.ventana_principal, height=2, bg="gray") linea.pack(fill="x", padx=20, pady=10) # Botón para buscar boton_buscar = tk.Button(self.ventana_principal, text="Buscar Equipos", command=self.buscar, font=("Arial", 12)) boton_buscar.pack(pady=10) # Lista para mostrar equipos self.lista_widget = tk.Listbox(self.ventana_principal, height=6) self.lista_widget.pack(pady=10, padx=20, fill="x") # Botón para seleccionar archivo boton_archivo = tk.Button(self.ventana_principal, text="Seleccionar Archivo", command=self.seleccionar, font=("Arial", 12)) boton_archivo.pack(pady=10) # Etiqueta para información self.etiqueta_info = tk.Label(self.ventana_principal, text="Esperando...", font=("Arial", 10)) self.etiqueta_info.pack(pady=5) # Botón para enviar self.boton_enviar = tk.Button(self.ventana_principal, text="ENVIAR", command=self.enviar, font=("Arial", 12), state="disabled") self.boton_enviar.pack(pady=10) # Etiqueta para estado self.etiqueta_estado = tk.Label(self.ventana_principal, text="", font=("Arial", 10)) self.etiqueta_estado.pack(pady=10) def buscar(self): """Busca otros equipos en la red""" # Limpiar lista self.lista_widget.delete(0, tk.END) self.etiqueta_info.config(text="Buscando...") # Buscar computadoras self.lista_equipos = buscar_computadoras() # Mostrar resultados if len(self.lista_equipos) > 0: for equipo in self.lista_equipos: self.lista_widget.insert(tk.END, equipo) self.etiqueta_info.config(text=f"Encontrados: {len(self.lista_equipos)}") else: self.etiqueta_info.config(text="No se encontraron equipos") def seleccionar(self): """Permite seleccionar un archivo""" # Importar aquí para no cargarlo al inicio from tkinter import filedialog archivo = filedialog.askopenfilename(title="Elegir archivo") if archivo: global ARCHIVO_A_ENVIAR ARCHIVO_A_ENVIAR = archivo nombre = os.path.basename(archivo) tamaño = os.path.getsize(archivo) self.etiqueta_info.config(text=f"Listo: {nombre}") self.boton_enviar.config(state="normal") def enviar(self): """Envía el archivo seleccionado""" # Obtener selección de la lista indices_seleccionados = self.lista_widget.curselection() if len(indices_seleccionados) == 0: self.etiqueta_estado.config(text="Error: Selecciona un equipo") return indice = indices_seleccionados[0] # Verificar índice válido if indice < 0 or indice >= len(self.lista_equipos): self.etiqueta_estado.config(text="Error: Equipo no válido") return # Obtener IP de destino global IP_DESTINO IP_DESTINO = self.lista_equipos[indice] # Verificar archivo seleccionado if not ARCHIVO_A_ENVIAR: self.etiqueta_estado.config(text="Error: No hay archivo") return # Cambiar estado self.etiqueta_estado.config(text="Enviando...") self.boton_enviar.config(state="disabled") # Enviar en segundo plano hilo_envio = threading.Thread(target=self.enviar_en_segundo_plano) hilo_envio.daemon = True hilo_envio.start() def enviar_en_segundo_plano(self): """Envía el archivo sin bloquear la interfaz""" resultado = mandar_archivo(ARCHIVO_A_ENVIAR, IP_DESTINO) # Actualizar interfaz if resultado: self.etiqueta_estado.config(text="¡Archivo enviado!") else: self.etiqueta_estado.config(text="Error al enviar") self.boton_enviar.config(state="normal") def iniciar(self): """Comienza la aplicación""" self.ventana_principal.mainloop() # ======================================== # PROGRAMA PRINCIPAL # ======================================== if __name__ == "__main__": print("Iniciando aplicación...") print(f"IP Local: {MI_IP}") print(f"Puerto: {PUERTO}") # Crear y ejecutar aplicación app = AplicacionTransferencia() app.iniciar()