博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
YModem协议
阅读量:6717 次
发布时间:2019-06-25

本文共 11603 字,大约阅读时间需要 38 分钟。

源:

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,不包括头和编码部分。

 

16CRC效验,高字节在前,低字节在后。

接收方收到第一帧数据包后,发送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 != '\0')               {                   *namptr++ = *bufptr++;               }               *namptr = '\0';               bufptr++;               while (*bufptr == ' ')               {                   bufptr++;               }               //file length               mblock->filelen = buf_filelen(bufptr);               //other data;               Uart_SendByte(MODEM_ACK);               return  0;           }           else if (2 == stat)         //取消传输           {               return 2;           }           else if (-3 == stat)           {               if (mblock->cur_num == 1)               {                   mblock->modemtype = 1;                   mblock->nxt_num = 2;                   return 1;               }           }           else                   //超时或校验方式不对           {               if (crc_tries-- <= 0)               {                   crc_tries = MODEM_CRC_RETRIES;                   mblock->crc_mode = (mblock->crc_mode+1) & 1;               }           }       }       return -1;   }      /*****************************************************************************************  ** 函数名称:  ** 函数功能:  ** 入口参数:  ** 返 回 值:0:成功接收数据                 -1:接收超时             -2:帧错误               -3:帧序号序号错误(严重错误)    1:消息结束              2:取消发送            ** 编    写:        日    期:      版 本 号:  ** 修改历史:  ******************************************************************************************/   int modem_recvdata(modem_struct *mblock)   {       int stat, hd_found=0, i;       int can_counter=0, eot_counter=0;       unsigned char *in_ptr = mblock->buf;       int cksum;       unsigned char ch, blk, cblk, crch, crcl;              Uart_RxEmpty();                         //接收缓冲区清空              if (mblock->nxt_num == 0)       {           if (mblock->crc_mode)           {               Uart_SendByte(MODEM_C);           }           else           {               Uart_SendByte(MODEM_NAK);           }       }       else       {           if (mblock->rec_err)           {               Uart_SendByte(MODEM_NAK);           }           else           {               if (mblock->nxt_num == 1)               {                   if (mblock->crc_mode)                   {                       Uart_SendByte(MODEM_C);                   }                   else                   {                       Uart_SendByte(MODEM_NAK);                   }               }               else               {                   Uart_SendByte(MODEM_ACK);               }           }       }       while (!hd_found)                               //头字节       {           stat = Uart_RecvByteTimeout(&ch);           if (stat == 0)           {               switch (ch)               {                   case MODEM_SOH :                       hd_found = 1;                       mblock->len = 128;                       break;                   case MODEM_STX :                       hd_found = 1;                       mblock->len = 1024;                       break;                   case MODEM_CAN :                       if ((++can_counter) >= MODEM_CAN_COUNT)                       {                           return 2;                       }                       break;                   case MODEM_EOT :                                //文件传输结束                       if ((++eot_counter) >= MODEM_EOT_COUNT)                       {                           Uart_SendByte(MODEM_ACK);                           if (mblock->modemtype == 2)         //Ymodem协议为批文件传输协议                           {                               Uart_SendByte(MODEM_C);          //单个文件需 C ACK C后会自动停止传输                               Uart_SendByte(MODEM_ACK);                               Uart_SendByte(MODEM_C);                               modem_cancle();               //多个文件强制停止传输                           }                           return 1;                       }                       break;                   default:                       break;               }           }           else           {               return -1;           }       }              stat = Uart_RecvByteTimeout(&blk);           //数据块错误或超时       if (stat != 0)       {           return -1;       }          stat = Uart_RecvByteTimeout(&cblk);           //数块补码       if (stat != 0)       {          return -1;       }          for (i=0; i < mblock->len ; i++)       {           stat = Uart_RecvByteTimeout(in_ptr++);           if (stat != 0)           {               return -1;           }       }              stat = Uart_RecvByteTimeout(&crch);         //CRC       if (stat != 0)       {           return -1;       }              if (mblock->crc_mode)       {           stat = Uart_RecvByteTimeout(&crcl);                        if (stat != 0)           {               return -1;           }       }          if (blk^cblk != 0xff)                              {           return (-2);       }          if (mblock->crc_mode)       {           in_ptr = mblock->buf;           cksum = 0;                      for (stat=mblock->len ; stat>0; stat--)           {               cksum = cksum^(int)(*in_ptr++) << 8;               for (i=8; i!=0; i--)               {                   if (cksum & 0x8000)                       cksum = cksum << 1 ^ 0x1021;                   else                       cksum = cksum << 1;               }           }           cksum &= 0xffff;                      if (cksum != (crch<<8 | crcl))           {               mblock->rec_err = 1;               return (-2);           }       }       else       {           for (i=0; i
len; i++) //和校验方式 { cksum += mblock->buf[i]; } if ((cksum&0xff)!=crch) { mblock->rec_err = 1; return (-2); } } mblock->cur_num = blk; if (blk != mblock->nxt_num) //blk检查 { return (-3); } mblock->nxt_num++; mblock->rec_err = 0; return 0; } unsigned int buf_filelen(unsigned char *ptr) { int datatype=10, result=0; if (ptr[0]=='0' && (ptr[1]=='x' && ptr[1]=='X')) { datatype = 16; ptr += 2; } for ( ; *ptr!='\0'; ptr++) { if (*ptr>= '0' && *ptr<='9') { result =result*datatype+*ptr-'0'; } else { if (datatype == 10) { return result; } else { if (*ptr>='A' && *ptr<='F') { result = result*16 + *ptr-55; //55 = 'A'-10 } else if (*ptr>='a' && *ptr<='f') { result = result*16 + *ptr-87; //87 = 'a'-10 } else { return result; } } } } return result; } void modem_cancle(void) { Uart_SendByte(0x18); Uart_SendByte(0x18); Uart_SendByte(0x18); Uart_SendByte(0x18); Uart_SendByte(0x18); }

 

你可能感兴趣的文章
中国太阳能续增 补贴、技术转型均受重视
查看>>
北京信息化协会人工智能专委会成立 AI产业快速腾飞
查看>>
《PostgreSQL服务器编程》一一1.9 关于缓存
查看>>
IBM芯片计划:生物是设计更高效芯片的关键
查看>>
没有这个黑客,就不会有你现在用的开源软件
查看>>
传统管理软件走在“生死边缘”,突围SaaS向死而生?
查看>>
这些数据科学技能,才是老板们最想要的
查看>>
大数据条件下政府信息化管理
查看>>
大数据+区块链将大有可为
查看>>
三大研究机构预测:6家公司吃掉80%云计算市场
查看>>
智能家居“吸金”新方式 家电或成救世主
查看>>
浙江电力使用RFID技术,有力保障电网运营
查看>>
呼叫中心管理之:让座席看见自己
查看>>
运营商全渠道建设的终极形态
查看>>
Java核心类库:内部类那点事儿
查看>>
《SAP入门经典(第5版)》——2.5 小结
查看>>
《软件建模与设计: UML、用例、模式和软件体系结构》一一1.8 软件建模和设计方法的发展...
查看>>
web 应用通用数据访问层 Fetchr
查看>>
《vSphere性能设计:性能密集场景下CPU、内存、存储及网络的最佳设计实践》一1.2 建立基准...
查看>>
绕过 Windows 10 Cloud 限制 成功运行 Win32 应用程序
查看>>