作业要求:
实现tftp功能:上传、下载
运行代码:
#include<myhead.h>
#define SER_PORT 69
#define SER_IP "192.168.1.101"
#define DOCU_SIZE 100
#define BUF_SIZE 516
void Prompt(int *app,char docu[]);
void tftp_app(int cfd,char buf[],char docu[],int app,struct sockaddr_in sin);//第一步申请
void download_data(int cfd,char buf[],char docu[],struct sockaddr_in sin);//第二步传输---下载
void upload_data(int cfd,char buf[],char docu[],struct sockaddr_in sin);//第二步传输---上传
void Prompt(int *app,char docu[])
{
printf("****1.下载****\n");
printf("****2.上传****\n");
printf("****3.退出****\n");
printf("你想干什么>>>");
scanf("%d",app);
if(*app==3){
return;
}
printf("请输入文件名>>>");
bzero(docu,DOCU_SIZE);
scanf("%s",docu);
while(getchar()!='\n');
}
/*********************请求*******************************/
void tftp_app(int cfd,char buf[],char docu[],int app,struct sockaddr_in sin)
{
short int *p0 = (short int *)buf;
*p0 = htons(app);//rd
char *p1 = buf+2;//文件名
strcpy(p1,docu);
char *p2 = p1+strlen(p1)+1;
strcpy(p2,"octet");
int buf_size = 2+strlen(p1)+1+strlen(p2)+1;
sendto(cfd,buf,BUF_SIZE,0,(struct sockaddr *)&sin,sizeof(sin));
}
/*********************下载******************************/
void download_data(int cfd,char buf[],char docu[],struct sockaddr_in sin)//第二步传输
{
int wfp = open(docu,O_WRONLY|O_TRUNC|O_CREAT,0664);
socklen_t addrlen = sizeof(sin);
short int num=0;
//发送ACK
while(1){
//接收信息
bzero(buf,BUF_SIZE);
int res=recvfrom(cfd,buf,BUF_SIZE,0,(struct sockaddr*)&sin,&addrlen);
if(res<=0){
break;
}
short int *p0 =(short int *)buf;
short int num =*(p0+1);
if(*p0!=htons(3)){
printf("下载过程出错\n");
printf("差错码>>>%d.差错信息>>>%s\n",htons(*((short int *)(buf+2))),buf+4);
return;
}
write(wfp,buf+4,BUF_SIZE-4);
//ACK发送
bzero(buf,BUF_SIZE);
short int *p_ack0=(short int *)buf;
*p_ack0=htons(4);
short int *p_ack1=p_ack0+1;
*p_ack1=num;
sendto(cfd,buf,4,0,(struct sockaddr *)&sin,sizeof(sin));
//判断结束
if(res<516){
printf("下载结束\n");
break;
}
}
close(wfp);
}
/***************************上传****************************/
void upload_data(int cfd,char buf[],char docu[],struct sockaddr_in sin)//第二步传输
{
int rfp = open(docu,O_RDONLY);
if(rfp == -1){
perror("rfd");
return;
}
socklen_t addrlen = sizeof(sin);
short int num=1;
//发送ACK
while(1){
//接收ACK
bzero(buf,BUF_SIZE);
recvfrom(cfd,buf,4,0,(struct sockaddr*)&sin,&addrlen);
short int *p_ack0=(short int *)buf;
//判断是否成功
if(*p_ack0!=htons(4)){
printf("上传失败\n");
printf("差错码>>>%d.差错信息>>>%s\n",htons(*((short int *)(buf+2))),buf+4);
}
//发送信息
bzero(buf,BUF_SIZE);
//前四位设置
short int *p0 =(short int *)buf;
*p0 = htons(3);
short int *p1 =p0+1;
*p1 = htons(num++);
//文件内容写入
int res = read(rfp,buf+4,BUF_SIZE-4);
sendto(cfd,buf,BUF_SIZE,0,(struct sockaddr *)&sin,sizeof(sin));
//判断结束
if(res<512){
printf("下载结束\n");
break;
}
}
close(rfp);
}
int main(int argc, const char *argv[])
{
//1.创建套接字文件
int cfd = -1;
if((cfd = socket(AF_INET,SOCK_DGRAM,0))==-1){
perror("socket");
return -1;
}
printf("%d success :cfd = %d\n",__LINE__,cfd);
//信息交互
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(SER_PORT);
sin.sin_addr.s_addr = inet_addr(SER_IP);
char buf[BUF_SIZE]={0};
char docu[DOCU_SIZE]="2.png";
int app=0;
#if 1
while(1){
Prompt(&app,docu);
tftp_app(cfd,buf,docu,app,sin);
switch(app){
case 1: download_data(cfd,buf,docu,sin);break;
case 2: upload_data(cfd,buf,docu,sin);break;
case 3: printf("正常退出\n");return 0;
}
}
#endif
//关闭文件
close(cfd);
return 0;
}