⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 receive.c

📁 linux下Y-Modem协议的实现源代码。 receive.c:数据接收代码 send.c:数据发送代码 ymodem.c:主文件
💻 C
字号:
#include     "ymodem.h"

/***************************************************************************/
unsigned int count_read=0;          /*the bytes of datas received from buffer. count from every packet begin*/
unsigned char PacketStartFlagRecv=1;/*indicate one packet begin*/
unsigned int PacketLen=0;
unsigned char blknum_cur=0;

char rxdata[1029];                   /* An 8-bit integerthat is not signed.*/
char first_flag=1;                   /*it should be set to 1 every time when a file ready to transfer*/
FILE* fp_recv=NULL;
char* filename;

char filename_change=0;		
unsigned int BlockLength;
unsigned int RealLen=0;    /*FileLen:record the file length left if this field in the first block*/
						   /*ReaLen: the real block length barring pads in the last block*/

char* get_name(unsigned char* rec_buf);
void get_length(unsigned int name_len,unsigned char* rec_buf);

int procheader(unsigned char* rec_buf);
int procrecdata(unsigned char* rec_buf);


int control_recv(char* device) 
{
	int head_check;
	int file_check;
	int i;	
	int len;
	int CAN_CNT=0;
	char bt;
	char test=1;
	
	bt='C';
	CrcFlag=1;   //bt="C":meant CRC check
	
	if((fd=_open(device, _O_RDWR|_O_BINARY|_O_NONBLOCK ))==-1)
		return(COM_OPEN_ERR);

	count_read=0;
	for(;;)
	{

		delay(10000000);

		if(_write(fd, &bt,1)==-1) //request sender to send file with CRC check
		{
			printf("write err!\n");
			_close(fd);
			return(COM_WRITE_ERR);
		}

		for(i=0;i<0x1fffff;i++)
			delay(0xffffffff);


		if((len=_read(fd,rxdata+count_read,1))==-1)
		{
			if(errno==EAGAIN)
			{
				if(test)
				{
					test=0;
					printf("waiting...............\n");
				}
				continue;
			}
			_close(fd);
			return(COM_READ_ERR);
		}

		if(len)
		{
#ifdef DEBUG
			printf("%x\n",rxdata[0]);
#endif
			count_read+=len;
			break;
		}

	}

	while(1)
	{		
		if((len=_read(fd,rxdata+count_read,1))==-1)
		{
			if(errno==EAGAIN)
			{
				continue;
			}
			printf("read fail!we have read %d bytes\n",count_read);

			return(COM_READ_ERR);
		}
		else
		{
			count_read+=len;
		}
		
		if(count_read)
		{
			if(PacketStartFlagRecv)
			{	
				PacketStartFlagRecv=0;
				switch(rxdata[0])
				{
					case SOH:
						if(CAN_CNT)
							CAN_CNT=0;
#ifdef DEBUG
						printf("SOH!128 bytes per packet!\n");
#endif
						PacketLen=133;	//CRC check :128+5
						BlockLength=128;
						break;
					case STX:
						if(CAN_CNT)
							CAN_CNT=0;
#ifdef DEBUG
						printf("STX!1024 bytes per packet!\n");
#endif
						PacketLen=1029; //case CRC check
						BlockLength=1024;
						break;
					case EOT:
					{
						if(CAN_CNT)
							CAN_CNT=0;
#ifdef DEBUG
						printf("get EOT!\n");
#endif

						printf("file has been completly transfered!\n");
						if(filename_change)
						{
							filename_change=0;
							printf("File existed! Save it as %s \n",filename);
						}
						printf("File length: %dbytes\n",FileLenBkup);
						
						
						if(*filename!=(char)NULL)
						{
							free(filename);
							*filename=(char)NULL;
						}

						RealLen=0;
						FileLen=0;
						PacketLen=0;
						count_read=0;
						blknum_cur=0;
						PacketStartFlagRecv=1;
						first_flag=1;		//wait for next file
						bt=(char)ACK;  // "ACK":config the file end
						if(_write(fd,&bt,1)==-1)
						{
							_close(fd);
							return(COM_WRITE_ERR);
						}
						bt='C';  //request continue transmission with CRC check
						if(_write(fd, &bt,1)==-1) //request sender to send file with CRC check
						{
							_close(fd);
							return(COM_WRITE_ERR);
						}
				    	
						break;

					}
					case CAN:
						CAN_CNT++;
						count_read=0;
						PacketStartFlagRecv=1;
						break;
					default:
					{
						if(CAN_CNT)
							CAN_CNT=0;
						printf("unvalid packet head,retry!the first data is:0x%x\n",rxdata[0]);
						PacketStartFlagRecv=1;
						count_read=0;
						bt=(char)NAK;  // "NAK":indicate retransmission
						if(_write(fd, &bt,1)==-1) //request sender to send file with CRC check
						{
							printf("write fail!\n");
							_close(fd);
							return(COM_WRITE_ERR);
						}			
					}
				}
			}
		}
		if(CAN_CNT==2)
		{
			printf("transmittion is canceled by user!\n");
			if(*filename!=(char)NULL)
				remove(filename);
			_close(fd);
			exit(0);
		}
		if(!count_read)	//get EOT or unvilid packet head or CAN
			continue;

		if(count_read==PacketLen)
		{
#ifdef DEBUG			
			printf("get a packet completly!count_read:%d\n",count_read);
#endif
			PacketStartFlagRecv=1;
			count_read=0;

			head_check=procheader(rxdata);
	    	
			switch(head_check)
			{
				case HEAD_OK:
#ifdef DEBUG
					printf("head check OK!\n");
#endif
					file_check=procrecdata(rxdata);
					
					switch(file_check)
					{
						case FILE_OPEN_ERR:
#ifdef DEBUG
							printf("ERROR occured when open the file!\n");
#endif
							if(first_flag)
							{
								bt=(char)NAK; //filename packet .retrans if error occured
								if(_write(fd, &bt,1)==-1) //request the sender to send file with CRC check
								{
									_close(fd);
									return(COM_WRITE_ERR);
								}
								
							}
							else
							{
								bt=(char)CAN;
								if(_write(fd, &bt,1)==-1) //request sender to send file with CRC check
								{
									_close(fd);
									return(COM_WRITE_ERR);
								}
								if(_write(fd, &bt,1)==-1) //request sender to send file with CRC check
								{
									_close(fd);
									return(COM_WRITE_ERR);
								}
								delay(10000000);
								_close(fd);
								exit(0);
							}
						case NO_MORE_FILE:
#ifdef DEBUG
							printf("Files have been transfered completly\n");
#endif
							bt=(char)ACK;  //加入发送编辑框对应字符串 "ACK";确认结束
							if(_write(fd, &bt,1)==-1) //request sender to send file with CRC check
							{
								_close(fd);
								return(COM_WRITE_ERR);
							}
							delay(10000000);
							_close(fd);
							exit(0);
						default:
#ifdef DEBUG
							printf("continue next packet.....\n");
#endif
							bt=(char)ACK;  //加入发送编辑框对应字符串 "ACK",指示继续
							if(_write(fd, &bt,1)==-1) //request sender to send file with CRC check
							{
								_close(fd);
								return(COM_WRITE_ERR);
							}

							if(first_flag)
							{
								bt='C';  //加入发送编辑框对应字符串 "C";指示以CRC检测的方式发送文件内容
								if(_write(fd, &bt,1)==-1) //request sender to send file with CRC check
								{
									_close(fd);
									return(COM_WRITE_ERR);
								}
							}
				
					}
					break;
				case FORMAT_UNSUPPORT:
#ifdef DEBUG
					printf("ERROR! Unsupported Format!\n");
#endif
					if(first_flag)
					{
						bt=(char)NAK; //文件名数据包,出错指示重发
						if(_write(fd, &bt,1)==-1) //request sender to send file with CRC check
						{
							_close(fd);
							return(COM_WRITE_ERR);
						}
					
					}
					else
					{
						bt=(char)CAN;  //加入发送编辑框对应字符串 "CAN";指示结束
						if(_write(fd, &bt,1)==-1) //request sender to send file with CRC check
						{
							_close(fd);
							return(COM_WRITE_ERR);
						}
						if(_write(fd, &bt,1)==-1) //request sender to send file with CRC check
						{
							_close(fd);
							return(COM_WRITE_ERR);
						}
						_close(fd);
						exit(FORMAT_UNSUPPORT);
					}
					break;
				case CRC_ERR:
#ifdef DEBUG
					printf("CRC ERROR!\n");
#endif
				case BLK_REPEAT:
#ifdef DEBUG
					printf("ERROR! Blocks repeat!\n");
#endif
					bt=(char)NAK;  //加入发送编辑框对应字符串 "NAK";指示重发
					if(_write(fd, &bt,1)==-1) //request sender to send file with CRC check
					{
						_close(fd);
						return(COM_WRITE_ERR);
					}
				
					break;
				case BLK_LOSS:
#ifdef DEBUG
					printf("ERROR! Blocks lost!\n");
#endif
					if(first_flag)
					{
						bt=(char)NAK; //文件名数据包,出错指示重发
						if(_write(fd, &bt,1)==-1) //request sender to send file with CRC check
						{
							_close(fd);
							return(COM_WRITE_ERR);
						}
//						delay(10000000);
					}
					else
					{
						bt=(char)CAN;  //加入发送编辑框对应字符串 "CAN";指示结束
						if(_write(fd, &bt,1)==-1) //request sender to send file with CRC check
						{
							_close(fd);
							return(COM_WRITE_ERR);
						}
						if(_write(fd, &bt,1)==-1) //request sender to send file with CRC check
						{
							_close(fd);
							return(COM_WRITE_ERR);
						}
						_close(fd);
						exit(-1);
					}
			}
		}

	}
}

/*************************************************************************/
/*************************************************************************/
int procheader(unsigned char* rec_buf)
{
	unsigned int i;
	unsigned short oldcrc=0,checksum=0;

	unsigned char blknum;
	
	/*check blocknum*/
	blknum=rec_buf[1];

	if(blknum!=blknum_cur)
	{
		if(blknum==blknum_cur-1)
		{
			blknum_cur-=1;
			return(BLK_REPEAT);
		}
		else
		{
			return(BLK_LOSS);
		}
	}
	
	blknum_cur=blknum+1;
	
	/*check crc*/
	if(CrcFlag)
	{

		for(i=3;i<BlockLength+5;i++)
		{
			oldcrc=updcrc(rec_buf[i], oldcrc);
		}
		
		if (oldcrc & 0xFFFF)
		{
			blknum_cur-=1;
			return(CRC_ERR);
		}

	}
	else
	{
	/**********************reserved for checksum Pro******************************/
		for(i=3;i<BlockLength+3;i++)
		{
			checksum+=rec_buf[i];
		}
		if((checksum-rec_buf[i])&0377) 
		{
			return(CHECKSUM_ERR);
		}
	}

	return(HEAD_OK);
}

/***************************************************************/
/***************get block;the first block has filename**********/
/***************************************************************/
int procrecdata(unsigned char* rec_buf)
{
//	int percent_new;


	if(first_flag&&(rec_buf[1]==0))   /*the first block (if num_blocks>256,needed first_flag)*/
	{
		
		filename=get_name(rec_buf);
		
		if(strlen(filename))
		{
			get_length(strlen(filename),rec_buf);  /*get FielLen*/

#ifndef WINYWY			
			while(access(filename,F_OK)==0)
			{
				strcat(filename,"~");
				if(!filename_change)
					filename_change=1;
			}
#endif

		}
		else
		{

			if(*filename!=(char)NULL)
			{
				free(filename);
				*filename=(char)NULL;
			}

			return(NO_MORE_FILE);/*empty file name:sender indicate no more files*/
		}
	}
	else
	{
#ifdef DEBUG
		printf("blknum:%d\n",rec_buf[1]);
#endif
		
		if(first_flag)
		{
			first_flag=0;
		}

		if((fp_recv=fopen(filename,"ab"))==NULL)
		{
			return(FILE_OPEN_ERR);
		}
		
		if(FileLen&&(FileLen<BlockLength))
		{
			RealLen=FileLen;
			FileLen=0;
		}
		else
		{
			RealLen=BlockLength;
			FileLen-=BlockLength;
		}
    	
		fwrite(rec_buf+3,RealLen,1,fp_recv);/*put the datas in file*/

		fclose(fp_recv);
	}
	return 0;
}

char* get_name(unsigned char* rec_buf)
{
	unsigned int i;
	char* file_name=(char*)malloc(BlockLength);
	
	memset(file_name,'\0',BlockLength);
	
	for(i=3;i<BlockLength+3;i++)
	{
		if(rec_buf[i]=='\0')
			break;
		else
			file_name[i-3]=rec_buf[i];
	}
	
	return file_name;
}

void get_length(unsigned int name_len,unsigned char* rec_buf)
{
	unsigned short i;
	unsigned char count_len=0;
	unsigned int pos_len;
	
	pos_len=name_len+4;

	for(i=pos_len;;i++)
	{
		if((rec_buf[i]!=0x20)&(rec_buf[i]!='\0'))/*space and null*/

			count_len++;
		else
			break;
	}
	for(i=pos_len;count_len>0;i++)
	{

		FileLen+=(unsigned int)((rec_buf[i]&0x0f)*pow(10,--count_len));

	}
	FileLenBkup=FileLen;
	return;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -