Necesito incluir rutinas básicas de envío de archivos y recepción de archivos en mi programa, y debe ser a través del protocolo ZMODEM. El problema es que estoy teniendo problemas para entender la especificación.Comprensión del protocolo ZMODEM
Como referencia, here is the specification.
La especificación no define las distintas constantes, por lo que aquí está a header file from Google.
Me parece que hay un montón de cosas importantes que deja sin definir en ese documento:
- Se refiere constantemente a ZDLE-codificación, pero ¿qué es? ¿Cuándo exactamente lo uso y cuándo no lo uso?
- Después de una trama de datos ZFILE, se transfieren los metadatos del archivo (nombre de archivo, fecha de modificación, tamaño, etc.). Esto es seguido por un bloque ZCRCW y luego un bloque cuyo tipo no está definido de acuerdo con la especificación. El bloque ZCRCW supuestamente contiene un CRC de 16 bits, pero la especificación no define en qué datos se calcula el CRC.
No define el polinomio CRC que utiliza. Descubrí por casualidad que el CRC32 poly es el CRC32 estándar, pero no he tenido tanta suerte con el CRC16 poly.No importa, lo encontré por prueba y error. El CRC16 poly es 0x1021.
He buscado el código de referencia, pero todo lo que puedo encontrar son archivos C ilegibles e indocumentados de principios de los 90. También he encontrado este conjunto de documentos de la MSDN, pero es dolorosamente vago y contradictorio a pruebas que me he encontrado: http://msdn.microsoft.com/en-us/library/ms817878.aspx (puede que tenga que ver que a través de Google's cache)
Para ilustrar mis dificultades, aquí es una ejemplo simple He creado un archivo de texto plano en el servidor que contiene "Hello world!", Y se llama helloworld.txt.
que iniciar la transferencia desde el servidor con el siguiente comando:
sx --zmodem helloworld.txt
Esto indica al servidor para enviar la trama siguiente ZRQINIT:
2A 2A 18 42 30 30 30 30 30 30 30 30 30 30 30 30 **.B000000000000
30 30 0D 8A 11 00.Š.
Tres problemas con esto:
- ¿Los bytes de relleno (0x2A) son arbitrarios? ¿Por qué hay dos aquí, pero en otros casos solo hay uno, y a veces ninguno?
- La especificación no menciona [CR] [LF] [XON] al final, pero sí el artículo de MSDN. ¿Por qué está ahí?
- ¿Por qué [LF] tiene el bit 0x80 establecido?
Después de esto, el cliente debe enviar un marco ZRINIT. Tengo este del artículo de MSDN:
2A 2A 18 42 30 31 30 30 30 30 30 30 32 33 62 65 **.B0100000023be
35 30 0D 8A 50.Š
Además de la cuestión de la bandera 0x80 [LF], tengo dos cuestiones más:
- ¿Por qué no se [XON] incluidos en esta ocasión?
¿Se calcula el CRC en los datos binarios o en los datos hexadecimales ASCII? Si está en los datos binarios obtengo 0x197C, y si está en los datos hexadecimales ASCII obtengo 0xF775; ninguno de estos es lo que está realmente en el cuadro (0xBE50).(Resuelto, sigue el modo que esté utilizando. Si está en modo BIN o BIN32, es el CRC de los datos binarios. Si está en modo hexadecimal ASCII, es el CRC de lo que representa el hex ASCII caracteres)
El servidor responde con un marco zfile:.
2A 18 43 04 00 00 00 00 DD 51 A2 33 *.C.....ÝQ¢3
OK. Esto tiene sentido. Si calculo el CRC32 de [04 00 00 00 00], de hecho obtengo 0x33A251DD. Pero ahora no tenemos CUALQUIER [CR] [LF] [XON] al final. ¿Por qué es esto?
Inmediatamente después de este marco, el servidor envía también los metadatos del archivo:
68 65 6C 6C 6F 77 6F 72 6C 64 2E 74 78 74 00 31 helloworld.txt.1
33 20 32 34 30 20 31 30 30 36 34 34 20 30 20 31 3 240 100644 0 1
20 31 33 00 18 6B 18 50 D3 0F F1 11 13..k.PÓ.ñ.
Esto no tiene ni siquiera una cabecera, sólo se salta directamente a los datos. OK, puedo vivir con eso. Sin embargo:
- Tenemos nuestro primer marco ZCRCW misterioso: [18 6B]. ¿Cuánto dura este marco? ¿Dónde están los datos CRC, y es CRC16 o CRC32? No está definido en ninguna parte de la especificación.
- El artículo de MSDN especifica que [18 6B] debe ir seguido de [00], pero no lo es.
- Luego tenemos un marco con un tipo indefinido: [18 50 D3 0F F1 11]. ¿Es este un marco separado o es parte de ZCRCW?
El cliente debe responder con un marco ZRPOS, de nuevo tomado del artículo de MSDN:
2A 2A 18 42 30 39 30 30 30 30 30 30 30 30 61 38 **.B0900000000a8
37 63 0D 8A 7c.Š
mismos problemas que con el marco ZRINIT: el CRC es incorrecto, el [LF] tiene bit 0x80 establecido, y no hay [XON].
el servidor responde con un marco ZDATA:
2A 18 43 0A 00 00 00 00 BC EF 92 8C *.C.....¼ï’Œ
mismos problemas que zfile: la CDN es todo muy bien, pero ¿dónde está el [CR] [LF] [XON]?
Después de esto, el servidor envía la carga del archivo. Dado que este es un ejemplo corto, cabe en un bloque (tamaño máximo es de 1024):
48 65 6C 6C 6F 20 77 6F 72 6C 64 21 0A Hello world!.
De lo que el artículo parece mencionar, cargas útiles se escapó con [ZDLE]. Entonces, ¿cómo puedo transmitir un byte de carga que coincide con el valor de [ZDLE]? ¿Hay otros valores como este?
El servidor termina con estos marcos:
18 68 05 DE 02 18 D0 .h.Þ..Ð
2A 18 43 0B 0D 00 00 00 D1 1E 98 43 *.C.....Ñ.˜C
estoy completamente perdido en la primera. El segundo tiene tanto sentido como los marcos ZRINIT y ZDATA.
Estoy trabajando exactamente de la misma manera precisamente por la misma razón; Si alguna vez hiciste esto, y tienes un código fuente, sería increíble ... –
¿Cómo terminó esto? Después de pasar unos días codificando para que ZMODEM recibiera el trabajo confiable, me di por vencido y simplemente le pedí a lrz. Trabajó en un día. No está ni cerca como limpio, pero realmente no tenía ganas de pasar más tiempo en un protocolo venerable pero obsoleto ... – bronson
Además, ¡cuidado! ¡Encontré algunas otras bibliotecas de código de zmodem pero eran completamente poco confiables! Probablemente el 5% de los archivos que probé terminaron en fracaso, y ni siquiera estaba tratando de explotar los casos de las esquinas. Asegúrate de usar código probado en batalla, no el proyecto de fin de semana de alguien. – bronson