完成tftp下载模型
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
//打印错误信息宏函数
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%d__",__LINE__);\
perror(msg);\
}while(0)
int main(int argc, const char *argv[])
{
if(argc<3)
{
fprintf(stderr,"请输入IP port\n");
return -1;
}
//将获取到的端口号字符串,转化为整形
int port = atoi(argv[2]);
int sfd=socket(AF_INET,SOCK_DGRAM,0);
if(sfd<0)
{
ERR_MSG("socket");
return -1;
}
//以写的方式打开一个文件
char name[128]="";
printf("请输入要下载文件名:");
fgets(name,sizeof(name),stdin);
name[strlen(name)-1]=0;
int fd_w=open(name,O_WRONLY|O_CREAT,0664);
if(fd_w<0)
{
ERR_MSG("open");
return -1;
}
//服务器地址结构体
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = inet_addr(argv[1]);
char buf[128]="";
//读写请求 1,填入操作码,并变为大端
char *ptr=buf;
short int *pa=(short int*)ptr;
*pa=htons(1);
char *pb=ptr+2;
//2,填入要下载的文件名
strcpy(pb,name);
//printf("name=%s\n",pb);
//填入"octet"
char *pc=pb+strlen(pb);
char *pd=pc+1;
strcpy(pd,"octet");
//printf("octet=%s\n",pd);
size_t size=2+strlen(pb)+1+strlen("octet")+1;
//发起请求
if(sendto(sfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin))<0)
{
ERR_MSG("send");
}
char data[600]="";
char ACK[4]="";
short int *p3=(short int*)ACK;
*p3=htons(4);
ssize_t res1=0;
//定义传输的数据地址结构体
struct sockaddr_in cin;
socklen_t addrlen=sizeof(cin);
while(1)
{
//接收数据包
bzero(data,sizeof(data));
res1=recvfrom(sfd,data,sizeof(data),0,(struct sockaddr*)&cin,&addrlen);
if(res1<0)
{
ERR_MSG("recvfrom");
return -1;
}
//printf("%ld\n",res1);
//判断错误码
char *p1=data;
short int*p2=(short int*)(p1);
short int bat2=ntohs(*p2);
if(5==bat2)
{
char* p5=p1+4;
printf("%s\n",p5);
}
//判断信息是否接收完毕
if(res1<516)
{
if(write(fd_w,p1+4,res1-4)<0)
{
ERR_MSG("write");
return -1;
}
break;
}
if(write(fd_w,p1+4,res1-4)<0)
{
ERR_MSG("write");
return -1;
}
//将接收到的数组前4个字节赋值ACK数组
short int *p4=(short int *)(data+2);
short int *p5=(short int*)ACK;
p5++;
*p5=*p4;
//发送回复ACK
if(sendto(sfd,ACK,sizeof(ACK),0,(struct sockaddr*)&cin,sizeof(cin))<0)
{
ERR_MSG("send");
}
}
close(sfd);
close(fd_w);
return 0;
}