源:YModem协议
YModem协议:
YModem协议是由XModem协议演变而来的,每包数据可以达到1024字节,是一个非常高效的文件传输协议。
下面先看下YModem协议传输的完整的握手过程:先看下图
SENDER:发送方。
RECEIVER:接收方。
第一步先由接收方,发送一个字符'C'
发送方收到'C'后,发送第一帧数据包,内容如下:
SOH 00 FF Foo.c NUL[123] CRC CRC
第1字节SOH:表示本包数据区大小有128字节。如果头为STX表示本包数据区大小为1024
第2字节00: 编号,第一包为00,第二包为01,第三包为02依次累加。到FF后继续从0循环递增。
第3字节FF: 编号的反码。 编号为00 对应FF,为01对应FE,以此类推。
第4字节到最后两字节:若第1字节为SOH时有128字节,为STX时有1024字节,这部分为数据区。“Foo.c” 文件名, 超级终端下,在文件名后还有文件大小。官方dome也是因为使用了这个文件大小进行比对。这就是为什么用SecureCRT中的YMODEM协议而无法正确传输的原因。在文件名和文件大小之后,如果不满128字节,以0补满。
最后两字节:这里需要注意,只有数据部分参与了效CRC验,不包括头和编码部分。
16位CRC效验,高字节在前,低字节在后。
接收方收到第一帧数据包后,发送ACK正确应答。
然后再发送一个字符'C'。
发送方收到'C'后,开始发送第二帧,第二帧中的数据存放的是第一包数据。
接收方收到数据后,发送一个ACK然后等待下一包数据传送完毕,继续ACK应答。直到所有数据传输完毕。
数据传输完毕后,发送方发EOT,第一次接收方以NAK应答,进行二次确认。
发送方收到NAK后,重发EOT,接收方第二次收到结束符,就以ACK应答。
最后接收方再发送一个'C',发送方在没有第二个文件要传输的情况下,
发送如下数据
SOH 00 FF 00~00(共128个) CRCH CRCL
接收方应答ACK后,正式结束数据传输。
以上部分,为YMODEM协议的基本操作流程。
/****************************************Copyright (c)************************************************** ** Henan Star Hi-Tech CO.,LTD ** All rights reserved. ** **----------------------------------------File Info----------------------------------------------------- ** 文件名称: ** 工程项目: ** 说 明: ** ** 作 者: 日 期: ** 建立版本: ** **----------------------------------------modification-------------------------------------------------- ** 作 者: ** 日 期: ** 版 本: 标 记: ** 说 明: ** ********************************************************************************************************/ #ifndef __XYMODEM_H_ #define __XYMODEM_H_ #define MODEM_MAX_RETRIES 50 //接收等待延时时间 #define MODEM_CRC_RETRIES 51 //>MODEM_MAX_RETRIES固定为CRC校验 #define MODEM_CAN_COUNT 3 //Wait for 3 times CAN before quiting #define MODEM_EOT_COUNT 1 #define MODEM_SOH 0x01 //数据块起始字符 #define MODEM_STX 0x02 #define MODEM_EOT 0x04 #define MODEM_ACK 0x06 #define MODEM_NAK 0x15 #define MODEM_CAN 0x18 #define MODEM_C 0x43 typedef struct{ int modemtype; int crc_mode; int nxt_num; //下一数据块序号 int cur_num; //当块序号 int len; int rec_err; //数据块接收状态 unsigned char buf[1024]; //数据 unsigned int filelen; //Ymodem可有带文件名称和长度 unsigned char filename[32]; }modem_struct; #ifdef __cplusplus extern "C"{ #endif int ymodem_init(modem_struct *mblock); int modem_recvdata(modem_struct *mblock); //int crc_16(unsigned char *buf, int len); void modem_cancle(void); #ifdef __cplusplus } #endif #endif
/****************************************Copyright (c)************************************************** ** Henan Star Hi-Tech CO.,LTD ** All rights reserved. ** **----------------------------------------File Info----------------------------------------------------- ** 文件名称: ** 工程项目: ** 说 明: ** ** 作 者: 日 期: ** 建立版本: ** **----------------------------------------modification-------------------------------------------------- ** 作 者: ** 日 期: ** 版 本: 标 记: ** 说 明: ** ********************************************************************************************************/ #include "xymodem1.h" #include "heads.h" unsigned int buf_filelen(unsigned char *ptr); /***************************************************************************************** ** 函数名称: ** 函数功能: ** 入口参数: ** 返 回 值: ** 编 写: 日 期: 版 本 号: ** 修改历史: ******************************************************************************************/ int ymodem_init(modem_struct *mblock) { int stat; int max_tries = MODEM_MAX_RETRIES; int crc_tries =MODEM_CRC_RETRIES; unsigned char *bufptr = mblock->buf; unsigned char *namptr = mblock->filename; mblock->nxt_num = 0; mblock->modemtype = 2; mblock->rec_err = 0; mblock->crc_mode = 1; while (max_tries-- > 0) { stat = modem_recvdata(mblock); if (0 == stat) //接收成功 { //file name while (*bufptr != '