Introducción
El puesto comunitario de descargas distribuye notas de campo de North Pier y un informe para voluntarios del jardín. Antes de cerrar, una persona quiere permitir que termine una descarga ya aceptada. La primera implementación cierra las conexiones inmediatamente. Primero obtendrás un documento completo y útil; después observarás exactamente qué interrumpe una parada inmediata.
Necesitas conocer funciones, manejadores y valores de error de Go, además de las responsabilidades de goroutines y canales de los dos proyectos anteriores, o tener experiencia equivalente. Aquí se presentan la identidad de procesos y SIGTERM. Los dos terminales con nombre son sesiones de la misma máquina. Las herramientas preparadas solo registran el servidor compilado del curso y sus procesos hijos curl; no necesitas aprender su formato de trazas nativas. Reserva unos 45 minutos, incluidos la lectura y los errores habituales; es una estimación del autor. Cada unidad comienza de forma independiente.
Descarga un documento completo
En este paso obtendrás un documento completo y útil y comprobarás sus bytes reales.
Empieza en Downloads. Las dos entradas de terminal solo acceden al espacio de trabajo existente; abrir una pestaña nunca reconstruye el escenario. Si cometes un error de directorio habitual, este comando visible devuelve la sesión a la ubicación correcta:
cd /home/labex/project/download-desk
Lee los dos archivos de texto originales. Contienen materiales prácticos distintos, no dos nombres para la misma muestra. cat muestra el contenido sin modificar los archivos.
cat documents/north-pier.txt documents/garden-route.txt
Conserva estos originales y todos los archivos preparados sin cambios durante la unidad. Puedes compilar desk, iniciar intentos observados con nombre y crear descargas. Esta unidad no modifica código Go. Cada unidad posterior proporciona su propia copia nueva.
Cambia a Server. El ejecutable de Go está preparado en su ruta absoluta. build compila este paquete; . significa el paquete actual y -o desk da nombre al ejecutable generado. Usar el binario compilado hace explícita la identidad del proceso, a diferencia de enviar señales a un envoltorio go run.
cd /home/labex/project/download-desk
/usr/local/go/bin/go build -o desk .
Inicia un intento con nombre. El observador suministrado ejecuta tu binario y registra su proceso real, peticiones HTTP, señales y salida nativa; no implementa el cierre ordenado. first es el nombre del intento. Rechaza nombres existentes para no sobrescribir silenciosamente las pruebas anteriores.
python3 desk.py serve first
Espera a Ready. Use Downloads for client requests.. Este terminal permanece ocupado hasta que sale el proceso original. El PID impreso es el hijo Go compilado, no el observador. Deja Server funcionando y cambia a Downloads.
El cliente preparado ejecuta curl real, registra su resultado nativo y guarda su salida efectiva. Sus cuatro argumentos seleccionan el intento, una etiqueta de salida nueva, un documento preparado y un retardo en milisegundos por cada 32 bytes. Un retardo de 0 es la muestra rápida normal. La etiqueta normal produce downloads/normal.txt.
python3 desk.py download first normal north-pier.txt 0
Espera Original curl native exit: 0. Cero indica que terminó la transferencia; por sí solo no demuestra el contenido. cmp compara los archivos reales byte a byte y no imprime nada si coinciden. Lee también el documento útil guardado:
cmp documents/north-pier.txt downloads/normal.txt
cat downloads/normal.txt
Si el cliente indica conexión rechazada, vuelve a Server y lee su salida existente. No inicies repetidamente otro proceso en el mismo puerto. Si Go indicó un error de compilación, corrige el directorio o compara el archivo preparado antes de compilar de nuevo. Un shell nuevo no hereda las variables de otro, pero ambas sesiones comparten los archivos y el intento observado.
Detén el servidor exacto durante una descarga aceptada
En este paso interrumpirás una transferencia realmente aceptada y distinguirás el fallo del cliente de la salida del servidor.
Empieza en Downloads mientras Server todavía ejecuta first. Un identificador de proceso, o PID, identifica un proceso actualmente en ejecución, pero el sistema operativo puede reutilizarlo después de su salida. El observador también comprueba la ruta del ejecutable, el identificador del usuario actual y los ticks de inicio de Linux de /proc para distinguir el proceso original. Envía señales solo al proceso compilado de este curso. No uses pkill, no señales al observador ni cambies procesos de la plataforma o la configuración del shell.
SIGTERM es una petición ordinaria de terminación. kill -TERM PID la envía a un PID preciso. No espera por sí mismo a las descargas ni demuestra que el proceso haya terminado. El programa Go preparado recibe la señal, llama inmediatamente a Close y retorna de main. Eso es lo que observarás, no una caída de red.
Lee el resto del paso, incluidos los fallos previstos y la recuperación, antes de iniciar la transferencia lenta. Después ejecuta los bloques en orden; no te detengas a aprender el siguiente concepto mientras corre esta petición de duración finita. Para este documento la ventana ronda medio minuto; no espera indefinidamente.
Inicia en segundo plano una descarga lenta de duración finita. & permite que este shell acepte el siguiente comando mientras trabaja el cliente; $! es el PID del último trabajo en segundo plano y la asignación guarda ese trabajo observador para leer después su resultado nativo con wait. El retardo público de 300ms se aplica entre escrituras de 32 bytes y deja tiempo para leer y cambiar de pestaña; es una transferencia controlada de entrenamiento, no una medición de rendimiento.
python3 desk.py download first interrupted north-pier.txt 300 & download_job=$!
Antes de detener nada, pide al observador que lea la petición nativa ya registrada. Este comando no envía una petición sustitutiva ni una señal. Debe informar de que el servidor original aceptó este cliente real y ambas identidades siguen presentes. curl puede almacenar en búfer las escrituras de archivos pequeños, por lo que un archivo temporalmente vacío no significa que la petición nunca empezara.
python3 desk.py accepted first interrupted
Obtén e inspecciona ahora la identidad original. $(...) guarda en una variable del shell el PID impreso por el comando; posteriormente "$server_pid", entre comillas, lo entrega como un único argumento. La herramienta rechaza una combinación obsoleta de PID/inicio/ejecutable/UID.
server_pid=$(python3 desk.py pid first)
python3 desk.py identity first
Envía la señal precisa únicamente después de observar la petición aceptada:
kill -TERM "$server_pid"
Lee el resultado del cliente original. wait espera al trabajo en segundo plano de este shell. El siguiente comando debe devolver 18, acompañado del mensaje de curl sobre bytes pendientes. Es una observación terminada de una transferencia fallida, no un comando cuyo fallo debas ocultar con un marcador de éxito.
wait "$download_job"
echo $? muestra inmediatamente el estado nativo anterior, que debe ser 18. Un cat posterior correcto sustituiría ese estado del shell; por eso debes leerlo enseguida:
echo $?
cat downloads/interrupted.txt
Compara con el original:
cmp documents/north-pier.txt downloads/interrupted.txt
Esta comparación debe devolver 1 e indicar que el archivo parcial terminó antes de tiempo. El texto recibido comienza con contenido real de North Pier, pero está incompleto. Ni un nombre coincidente ni un archivo no vacío demuestran una descarga completa y útil. Cambia a Server y lee Original server native exit: 0. Un servidor que sale normalmente puede haber interrumpido a sus clientes.
Vuelve a Downloads y conserva ambos resultados. La comprobación solo lee observaciones existentes y archivos reales; nunca detiene un proceso activo ni crea por ti la interrupción que falte.
Si esperaste tanto que la transferencia terminó antes de la señal, no la llames interrupción. Lee su resultado nativo 0, compara todos sus bytes y consérvala. Si first sigue funcionando, inicia el mismo comando lento con una etiqueta nueva, como interrupted2, guarda su nuevo trabajo y usa esa misma etiqueta en accepted antes de señalar. Si el servidor original ya salió, cambia a Server e inicia explícitamente otro intento, como retry1, conservando el anterior; usa después ese nombre y una salida nueva en los comandos download, accepted, pid e identity. La comprobación acepta estos nombres nuevos. Repite una observación real en lugar de copiar un archivo parcial. Una transferencia terminada o desconocida no autoriza otra señal a un PID reciclado.
Esta es una repetición completa en el mismo intento first todavía activo. Úsala solo cuando el cliente anterior haya terminado realmente; conserva downloads/interrupted.txt. Lee todos estos bloques antes de empezar. La etiqueta nueva crea una salida independiente:
python3 desk.py download first interrupted2 north-pier.txt 300 & download_job=$!
python3 desk.py accepted first interrupted2
server_pid=$(python3 desk.py pid first)
python3 desk.py identity first
kill -TERM "$server_pid"
La siguiente espera también debe devolver 18; léelo inmediatamente y compara el nuevo archivo parcial real (la comparación debe devolver 1):
wait "$download_job"
echo $?
cmp documents/north-pier.txt downloads/interrupted2.txt
Si first ya salió, inicia otro intento en Server:
python3 desk.py serve retry1
Tras su mensaje de disponibilidad, ejecuta esta secuencia completa en Downloads, con una tercera etiqueta de salida nueva:
python3 desk.py download retry1 interrupted3 north-pier.txt 300 & download_job=$!
python3 desk.py accepted retry1 interrupted3
server_pid=$(python3 desk.py pid retry1)
python3 desk.py identity retry1
kill -TERM "$server_pid"
wait "$download_job"
echo $?
La espera debe devolver 18. Conserva la salida real y verifica que está incompleta (la comparación debe devolver 1):
cmp documents/north-pier.txt downloads/interrupted3.txt
Termina con el puesto original detenido y los resultados conservados. La descarga normal ya está completa y sigue disponible para leer; no dejes un listener sustituto funcionando antes de la comprobación. La siguiente unidad independiente enseña a preservar transferencias activas.
Resumen
Observaste una descarga real completa y relacionaste una transferencia interrumpida con la parada precisa de su servidor original. Una conexión rechazada, una transferencia parcial y la salida normal de un proceso describen hechos diferentes.



