YModem协议

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

 

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

接收方收到第一帧数据包后,发送ACK正确应答。

然后再发送一个字符'C'

发送方收到'C'后,开始发送第二帧,第二帧中的数据存放的是第一包数据。

接收方收到数据后,发送一个ACK然后等待下一包数据传送完毕,继续ACK应答。直到所有数据传输完毕。

数据传输完毕后,发送方发EOT,第一次接收方以NAK应答,进行二次确认。

发送方收到NAK后,重发EOT,接收方第二次收到结束符,就以ACK应答。

最后接收方再发送一个'C',发送方在没有第二个文件要传输的情况下,

 

发送如下数据

SOH 00 FF 00~00(128) CRCH CRCL 

接收方应答ACK后,正式结束数据传输。

以上部分,为YMODEM协议的基本操作流程。

 

 

源:ymodem协议c实现

/****************************************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<mblock->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);   
}  

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/458032.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

gcc、clang、make、cmake、makefile、CMakeLists.txt概念学习

说明 编译器是翻译代码为计算机语言的一个工具&#xff0c;我们平时写的代码如果想在某个特定的计算机上执行&#xff08;计算机的cpu构架不同&#xff09;&#xff0c;就需要编译器来对代码进行编译汇编链接&#xff0c;而汇编和链接的过程对于每个不同的平台上过程都不一样。…

视觉在无人驾驶中的应用及分类_机器视觉在智能化生产中的广泛应用

什么是机器视觉&#xff1f;顾名思义&#xff0c;简单来说&#xff0c;机器视觉就是用机器代替人眼来测量和判断。机器视觉系统是指通过机器视觉产品将被摄取目标转换成图像信号&#xff0c;传送给专用的图像处理系统&#xff0c;根据像素分布和亮度、颜色等信息&#xff0c;转…

Socket编程实践(3) 多连接服务器实现与简单P2P聊天程序例程

SO_REUSEADDR选项 在上一篇文章的最后我们贴出了一个简单的C/S通信的例程。在该例程序中&#xff0c;使用"Ctrlc"结束通信后&#xff0c;服务器是无法立即重启的&#xff0c;如果尝试重启服务器&#xff0c;将被告知&#xff1a; bind: Address already in use 原因在…

work2的code和问题

//常量 package cn.itcast.work2; public class Constant { //constant 常量   public static void main(String[] args) { /* * 字符串常量 用双引号括起来的内容 * 整数常量 所有整数 * 小数常量 所有小数 * 字符常量 用单引号括起来的内容,里面只能放单个数字,单个字母或单…

Linux-(C/C++)生成并使用静态库/动态库

静态库/动态库概要 在Windows下静态库的后缀为&#xff1a;.lib、动态库后缀为&#xff1a;.dll&#xff1b;而在Linux下静态库的后缀为&#xff1a;.a、动态库的后缀为&#xff1a;.so。 那么什么是静态库呢&#xff1f; 首先我们来看看程序编译的大体流程&#xff1a;预处理…

windows下最好的围棋_学围棋能使学习成绩提高吗?

孩子几岁开始学习围棋最合适&#xff1f;当然要4岁开始学围棋。一是因为&#xff1a;4岁是幼儿形状知觉形成的关键期&#xff0c;围棋千变万化的棋形(见文后图)是最有利于促进与锻炼孩子形状知觉的形成。二是因为&#xff1a;人的大脑在3周岁后基本已经发育了60%&#xff0c;到…

C#与C/C++的交互zz

C#与C交互&#xff0c;总体来说可以有两种方法&#xff1a; 利用C/CLI作为代理中间层 利用PInvoke实现直接调用 第一种方法&#xff1a;实现起来比较简单直观&#xff0c;并且可以实现C#调用C所写的类&#xff0c;但是问题是MONO构架不支持C/CLI功能&#xff0c;因此无法实现脱…

curl查看swift状态命令_HTTP 请求与响应包括哪些,如何用Chrome查看 HTTP 请求与响应内容和curl 命令的使用...

1.HTTP的请求和响应其实就是通过电脑上的软件来进行的&#xff0c;客户端请求的内容发送到服务器上&#xff0c;服务器收到请求后就会响应客户端的请求&#xff0c;如图&#xff1a;HTTP请求的内容及格式&#xff1a;请求最多包含四部分&#xff0c;最少包含三部分。&#xff0…

Pytorch的BatchNorm层使用中容易出现的问题

前言 本文主要介绍在pytorch中的Batch Normalization的使用以及在其中容易出现的各种小问题&#xff0c;本来此文应该归属于[1]中的&#xff0c;但是考虑到此文的篇幅可能会比较大&#xff0c;因此独立成篇&#xff0c;希望能够帮助到各位读者。如有谬误&#xff0c;请联系指出…

android 比较靠谱的图片压缩

2019独角兽企业重金招聘Python工程师标准>>> 第一&#xff1a;我们先看下质量压缩方法&#xff1a; private Bitmap compressImage(Bitmap image) { ByteArrayOutputStream baos new ByteArrayOutputStream(); image.compress(Bitmap.CompressFormat.JPEG, 100, …

常用公差配合表图_ER弹簧夹头配套BT刀柄常用规格型号表

ER弹簧夹头具有定心精度高&#xff0c;夹紧力均匀的特点&#xff0c;广泛用于机械类零件的精加工和半精加工&#xff0c;通常与BT刀柄匹配使用。BT刀柄是是机械主轴与刀具和其它附件工具连接件&#xff0c;BT为日本标准(MAS403)&#xff0c;现在也是普遍使用的一种标准。传统刀…

Linux下python安装升级详细步骤 | Python2 升级 Python3

Linux下python升级步骤 Python2 ->Python3 多数情况下&#xff0c;系统自动的Python版本是2.x 或者yum直接安装的也是2.x 但是&#xff0c;现在多数情况下建议使用3.x 那么如何升级呢&#xff1f; 下面老徐详细讲解升级步骤&#xff1b; 首先下载源tar包 可利用linux自带下…

华为手机连电脑_手机、电脑无网高速互传!华为神技逆天

Huawei Share是华为的一项自研多终端传输技术&#xff0c;可以在没有网络状态下实现手机与手机、电脑等多终端设备间快速稳定的文件分享&#xff0c;尤其是在办公场景下&#xff0c;可以极大提升办公效率。华为表示&#xff0c;未来Huawei Share将应用于更多全场景跨设备无缝分…

excel统计行数_值得收藏的6个Excel函数公式(有讲解)

收藏的Excel函数大全公式再多&#xff0c;几天不用也会忘记。怎么才能不忘&#xff1f;你需要了解公式的运行原理。小编今天不再推送一大堆函数公式&#xff0c;而是根据提问最多的问题&#xff0c;精选出6个实用的&#xff0c;然后详细的解释给大家。1、计算两个时间差TEXT(B2…

Studio One正版多少钱 Studio One正版怎么购买

随着版权意识的增强&#xff0c;打击盗版的力度越来越大&#xff0c;现在网络上的盗版资源越来越少&#xff0c;资源少很难找是一方面&#xff0c;另一方面使用盗版软件不仅很多功能不能使用&#xff0c;而且很多盗版软件都被植入各种木马病毒&#xff0c;从而带来各种各样的风…

DNS简述

常见DNS记录SOA&#xff1a;域权威开始NS&#xff1a;权威域名服务器A&#xff1a;主机地址CNAME&#xff1a;别名对应的正规名称MX&#xff1a;邮件传递服务器PTR&#xff1a;域名指针 (用于反向 DNS)查询过程浏览器缓存->hosts->LDNS->LDNS缓存->ISP->ISP缓存…

cuda gpu相关汇总

1.Ubuntu16.04:在anaconda下安装pytorch-gpu 转自&#xff1a;Ubuntu16.04:在anaconda下安装pytorch-gpu_莫等闲996的博客-CSDN博客 1 创建虚拟环境并进入 conda create -n pytorch-gpu python3.6 conda activate pytorch-gpu 2 下载对应的安装包和配件 方法一(推荐)&#…

普通人学python有意义吗_学python难吗

首先&#xff0c;对于初学者来说学习Python是不错的选择&#xff0c;一方面Python语言的语法比较简单易学&#xff0c;另一方面Python的实验环境也比较容易搭建。学习Python需要的时间取决于三方面因素。(推荐学习&#xff1a;Python视频教程)其一是学习者是否具有一定的计算机…

在Visual Studio上开发Node.js程序(2)——远程调试及发布到Azure

【题外话】 上次介绍了VS上开发Node.js的插件Node.js Tools for Visual Studio&#xff08;NTVS&#xff09;&#xff0c;其提供了非常方便的开发和调试功能&#xff0c;当然很多情况下由于平台限制等原因需要在其他机器上运行程序&#xff0c;进而需要远程调试功能&#xff0c…

服务器定期监控数据_基础设施硬件监控探索与实践

本文选自 《交易技术前沿》总第三十六期文章(2019年9月)陈靖宇深圳证券交易所 系统运行部Email: jingyuchenszse.cn摘要&#xff1a;为了应对基础设施规模不断上升&#xff0c;数据中心两地三中心带来的运维挑战&#xff0c;深交所结合现有基础设施现状&#xff0c;以通用性、灵…