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

📄 send.c

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

unsigned char Eot_Send=0;           /*if control program has send "C" to request send,then it should be set to 1*/
unsigned char FirstPackSend=0;
unsigned char SOH_Idx=0;	        /*SOH_Idx:1 128 bytes; 2:1024 bytes(STX:02)*/
unsigned int blk_num_send=0;
unsigned char file_send_end=0;       /*indicate the file has been sended*/
unsigned char file_send_end_ACK=0;   /*indicate the file has been sended and receiver responsed*/
unsigned char file_name_send_ACK=0;  /*indicate the file name packet has been sended*/
unsigned char FirstSend=1;           /*indicate the file name packet start to be sended*/
unsigned char PacketStartFlagSend=0; /*indicate the file content packet start to be sended*/
unsigned char NoWait=0;              /*if get 'G' command, no wait the next cmd*/
unsigned char No_More_File=0;        /*indicate all the files has been sended*/
unsigned char Empty_Ind=0;

unsigned int NumBlks;	             /*the number of blocks of the file*/
unsigned int LenLastBlk;             /*length of the last block*/
unsigned char SOHLastBlk;            /*the SOH ind of the last block*/

int get_filelen(char* file_name);
char* get_file_name(char* file_name);
int real_send(char* file_name);
int procsend(char* send_buf,char* file_name);
int Procpacket(char* send_buf,char* file_name);

int control_send(char* file_name,char* device)
{
	char send_next;
	int send_idx;

	char cmd_ind;
	int len;
	int CAN_CNT=0;
	int CAN_CNT1=0;
	
	if((fd=_open(device, _O_RDWR|_O_BINARY|_O_NONBLOCK ))==-1)
		return(COM_OPEN_ERR);


	for(;;)
	{	
		if((len=_read(fd,&cmd_ind,1))==-1)
        {
        	if(errno==EAGAIN)
				continue;
            
            _close(fd);
		
			return(COM_READ_ERR);
        }

		switch(cmd_ind)
		{
			case 'C':
				if(CAN_CNT)
					CAN_CNT=0;
				if(FirstSend|file_name_send_ACK|file_send_end_ACK)
				{
					if(file_send_end_ACK)
					{
						Empty_Ind=1;
					}
 					CrcFlag=1;
					break;
				}
				else
				{
					printf("unvalid request:0x%x!\n",cmd_ind);
					continue;
				}
			case 'G':
				if(CAN_CNT)
					CAN_CNT=0;
				if(PacketStartFlagSend)
				{
					FirstPackSend=0; //indicate filename has been sended successfully.
					file_name_send_ACK=1;
					NoWait=1;
					break;
				}
				if(FirstSend|file_send_end_ACK)
				{
					if(file_send_end_ACK)
					{
						Empty_Ind=1;
					}
 					CrcFlag=1;
					break;
				}
				else
				{
					printf("unvalid request:0x%x!\n",cmd_ind);
					continue;
				}

			case NAK:
				if(CAN_CNT)
					CAN_CNT=0;
				if(FirstPackSend)
				{
					FirstSend=1;
					PacketStartFlagSend=0;
					blk_num_send-=1; //resend filename packet
					break;
				}
				if(file_name_send_ACK|FirstSend)
					CrcFlag=0;
				else if(PacketStartFlagSend)
				{
					printf("unvalid request:0x%x!\n",cmd_ind);
					continue;
				}
				else
				{
					blk_num_send-=1; //ressend data packet
					break;
				}
				
			case ACK:
				if(CAN_CNT)
					CAN_CNT=0;
				if(FirstSend)
				{
					printf("unvalid request!:0x%x\n",cmd_ind);
					continue;

				}
				if(PacketStartFlagSend)
				{
					FirstPackSend=0; //indicate filename has been sended successfully.
					file_name_send_ACK=1;

					continue;
				}
				if(Eot_Send)
					file_send_end_ACK=1;
				break;
			case CAN:
			{
				CAN_CNT++;
				if(CAN_CNT==2)
				{
					printf("the transmission is canceled by user!\n");
					_close(fd);
					exit(0);
				}
				continue;
			}
				
			default:
			{
				if(CAN_CNT)
					CAN_CNT=0;
				printf("unvalid request!:0x%x\n",cmd_ind);
				continue;
			}
		}
		send_next=1;
		for(;send_next;)
		{
			send_next=0;
			if(NoWait)
			{
				send_next=1;
#ifndef WINYWY	
				if((len=_read(fd,&cmd_ind,1))==-1)
        		{
        			if(errno!=EAGAIN)
        			{
           			 	_close(fd);
						return(COM_READ_ERR);
					}
        		}
        		if(len)
        		{
        			if(cmd_ind==CAN)
        			{
        				CAN_CNT1++;
        				if(CAN_CNT1==2)
        				{
        					printf("the transmission is canceled by user!\n");
							_close(fd);
							exit(0);
        				}
        			}
        			else
        			{
        				CAN_CNT1=0;
        			}
        		}
#endif
			}

			if(!Empty_Ind)
			{
				if(file_send_end)//send "EOT" to indicate end
				{
					cmd_ind=(char)(EOT);
					if(_write(fd,&cmd_ind,1)==-1)
					{
						printf("EOT write err!\n");
						_close(fd);
						return(COM_WRITE_ERR);
					}
					Eot_Send=1;
					if(NoWait)
						send_next=0;					
					continue;
				}
			}	
			send_idx=real_send(file_name);	//transmit the data packet
	

			if(send_idx==ALL_NEED_OFFSET)//just one file.if more files ,need modify
			{
				continue;
			}
			else if(send_idx!=0)
			{
				_close(fd);
				return(send_idx);//error occured while sending
			}
		
			if(PacketStartFlagSend)//used to know the "NAK" indicate re-send or just checksum
				PacketStartFlagSend=0;
			
			if(FirstSend)
			{
				FirstSend=0;//never resend file name packet?
				PacketStartFlagSend=1;
			}
		}
	}
	
}

int real_send(char* file_name)
{
	char send_buf[1029]; //max value:1(SOH)+1(Blk#)+1(255-Blk#)+1024(data)+2(crc)
	int frame_idx;
	unsigned int packet_len;
	unsigned int i;


	if(Empty_Ind)
		blk_num_send=0;
	else if(!FirstSend)
		blk_num_send++;

	frame_idx=procsend(send_buf,file_name);	
	if(frame_idx)
	{
		return(frame_idx);//error occured
	}
	if(SOH_Idx==1)
		packet_len=132;
	else
		packet_len=1028;
		
	if(CrcFlag)
		packet_len+=1;
		
	for(i=0;i<packet_len;i++)
	{

		if(_write(fd,send_buf+i,1)==-1)
		{
			printf("data write err!\n");
			return(COM_WRITE_ERR);
		}
	}
	if(No_More_File)
	{
		delay(10000000);
		exit(0);
	}	
		
	if(blk_num_send==NumBlks)//the last block has been sended successful.
	{
		file_send_end=1;
		return(ALL_NEED_OFFSET);//发送完一个文件,所有参数复位继续发送下一个文件
	}	
	
	return 0;

}
/***************************************************************/
/***************************************************************/
int procsend(char* send_buf,char* file_name)
{
	unsigned int blklen,i;

	char* filename_real;
	unsigned int size_rec;

	unsigned short oldcrc=0;
	unsigned char checksum=0;

	int get_filelenind;

	char packet_ind;
	
	if(FirstSend)/*file name packet*/
	{
		get_filelenind=get_filelen(file_name);
		if(get_filelenind)
			return(get_filelenind);
			
		LenLastBlk=FileLen%1024;
		NumBlks=(FileLen>>10);
		
		filename_real=get_file_name(file_name);//malloc a space,need be freed
		if((filename_real==(char*)FILE_UNVILID)||(filename_real==(char*)MALLOC_ERROR))
			exit((int)filename_real);
			
		if(LenLastBlk)
		{
			NumBlks+=1;
			

			if(LenLastBlk<128)
			{
				SOHLastBlk=1;
			}
			else
			{
				SOHLastBlk=2;
			}

		}
		else
		{
			LenLastBlk=1024;
		}
		if(strlen(filename_real)>128)
		{
			SOH_Idx=2;
			blklen=1024;
		}
		else
		{
			SOH_Idx=1;
			blklen=128;
		}
		if(CrcFlag)
			memset(send_buf,'\0',blklen+5);
		else
			memset(send_buf,'\0',blklen+4); //sumcheck
		
		send_buf[0]=SOH_Idx;
		send_buf[1]=0;
		send_buf[2]=(char)0xFF;
		
		size_rec=strlen(filename_real);
		strncpy(send_buf+3,filename_real,size_rec);
		
		size_rec+=4; //move to the position to packet file length
		
		sprintf(send_buf+size_rec,"%d",FileLen);
		
		/************reserved for crc or sumcheck**************/
		for (i=0;i<blklen;i++ ) 
		{
			oldcrc=updcrc((0377& send_buf[i+3]), oldcrc);
			checksum += send_buf[i+3];
		}
		if(CrcFlag)
		{
			oldcrc=updcrc(0,updcrc(0,oldcrc));
			send_buf[blklen+3]=(oldcrc>>8);
			send_buf[blklen+4]=(oldcrc&0xFF);
		}
		else
		{
			send_buf[blklen+3]=checksum;
		}

		free(filename_real);
		FirstPackSend=1;
		return 0;
	}
	else
	{

		if(blk_num_send<=NumBlks)
		{
			
			if(Empty_Ind) //send empty packet
				SOH_Idx=1;
			else
				SOH_Idx=2;
			packet_ind=Procpacket(send_buf,file_name);
		}

		return(packet_ind);
	}
}


/***************************************************************/
/***************************************************************/
int Procpacket(char* send_buf,char* file_name)
{
	//FILE* fp_send;
	int fd_send;
	unsigned int size_read;
	unsigned int blklen;
	unsigned short oldcrc=0;
	unsigned char checksum=0;
	unsigned int i;
	
	if((fd_send=_open(file_name,_O_RDONLY|_O_BINARY))==-1)
	{
		printf("can't open file %s for read!\n",file_name);
		return(FILE_OPEN_ERR);
	}
	
	send_buf[0]=SOH_Idx;
	
	send_buf[1]=(blk_num_send&0xFF);
	send_buf[2]=255-blk_num_send;
	
	if(blk_num_send==NumBlks)
	{
		SOH_Idx=SOHLastBlk;
		size_read=LenLastBlk;
		if(SOH_Idx==1)
			blklen=128;
		else
			blklen=1024;
	}
	else
	{
		if(SOH_Idx==1)
			size_read=128;
		else
			size_read=1024;	//STX
		blklen=size_read;
	}
	
	
	if(!file_send_end)
	{
		_lseek(fd_send,FileLenBkup-FileLen,SEEK_SET);
		//data part

		if(_read(fd_send,send_buf+3,size_read)==-1)
		{
			return(FILE_READ_ERR);
		}
	}
	FileLen-=size_read;

	_close(fd_send);
	
	if(Empty_Ind)
	{
		memset(send_buf+3,'\0',blklen); 
		No_More_File=1;  //now only for one file
	}

	//filled the last block with CPMEOF
	if(blk_num_send==NumBlks)
		memset(send_buf+3+size_read,CPMEOF,blklen-size_read);
	
	for (i=0;i<blklen;i++ ) 
	{
		oldcrc=updcrc((0377& send_buf[i+3]), oldcrc);
		checksum += send_buf[i+3];
	}
	
	//CRC and checksum part.
	if(CrcFlag)
	{
		oldcrc=updcrc(0,updcrc(0,oldcrc));
		send_buf[blklen+3]=(oldcrc>>8);
		send_buf[blklen+4]=(oldcrc&0xFF);
	}
	else
	{
		send_buf[blklen+3]=checksum;
	}
	
	return 0;
}


/***************************************************************/
/***************************************************************/
int get_filelen(char* file_name)
{
	FILE* fp_send;
	int c;
	
	if( (fp_send = fopen( file_name, "rb" )) == NULL )
	{
		printf("can't open file %s for read!\n",file_name);
		return(FILE_OPEN_ERR);
	}
	
	/* Cycle until end of file reached: */

	while((c=fgetc(fp_send))!=EOF)
		FileLen++;

	fclose( fp_send );
	
	FileLenBkup=FileLen;
	return(0);
}


/***************************************************************/
/***************************************************************/
/*need be freed*/
char* get_file_name(char* file_name)
{
	unsigned int real_name_len=0,name_len;
	unsigned int i;
	char* filename_real;
	char seperater;

#ifdef WINYWY
	seperater='\\';
#else
	seperater='/';
#endif
	name_len=strlen(file_name);
	
	for(i=1;i<name_len+1;i++)
	{
		if(*(file_name+(name_len-i))!=seperater)
		{
			real_name_len++;
		}
		else
		{
			break;
		}
	}
	
	if(!real_name_len)
	{
		return((char*)FILE_UNVILID);
	}	
	
	if((filename_real=(char*)malloc(real_name_len+1))==NULL)
	{
		return((char*)MALLOC_ERROR);
	}

	for(i=1;i<real_name_len+1;i++)
	{
		filename_real[real_name_len-i]=*(file_name+(name_len-i));
	}
	filename_real[real_name_len]='\0';
	
	return(filename_real);
}

⌨️ 快捷键说明

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