TFTP协议
#include<my_head.h>
#define PORT 69
#define IP "192.168.125.220"
int do_download(int cfd,struct sockaddr_in sin);
int do_upload(int cfd,struct sockaddr_in sin);
int main(int argc, const char *argv[])
{
int cfd =socket(AF_INET,SOCK_DGRAM,0);
if(cfd<0)
{
ERR_MSG("socket");
return -1;
}
printf("socket success sfd=%d\n",cfd);
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(PORT);
sin.sin_addr.s_addr=inet_addr(IP);
char choose;
while(1)
{
printf("----------------------------------\n");
printf("--------------1.下载--------------\n");
printf("----------------------------------\n");
printf("--------------2.上传--------------\n");
printf("----------------------------------\n");
printf("--------------3.退出--------------\n");
printf("----------------------------------\n");
printf("请输入:");
choose=getchar();
while(getchar()!=10);
switch(choose)
{
case '1':
do_download(cfd,sin);
break;
case '2':
do_upload(cfd,sin);
break;
case'3':
goto END;
}
}
END:
close(cfd);
return 0;
}
int do_download(int cfd,struct sockaddr_in sin)
{
char name[20]="";
printf("请输入文件名:");
scanf("%s",name);
getchar();
//组下载协议
char buf[516]="";
unsigned short *p1=(unsigned short *)buf;
*p1=htons(1);
char * p2= (char *)(p1+1);
strcpy(p2,name);
char * p3=p2+strlen(p2)+1;
strcpy(p3,"octet");
//发送下载协议给服务器
int size=2+strlen(p2)+1+strlen(p3)+1;
if(sendto(cfd,buf,size,0,(struct sockaddr *)&sin,sizeof(sin))<0)
{
ERR_MSG("sendto");
return -1;
}
//printf("sendto success\n");
int fd=open(name,O_WRONLY|O_CREAT|O_TRUNC,0664);
//创建新的结构体 接收服务器的随机端口和ip
struct sockaddr_in newsin;
socklen_t len=sizeof(newsin);
while(1)
{
//接收数据包
ssize_t res=0;
res = recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr *)&newsin,&len);
if(res<0)
{
ERR_MSG("recvfrom");
return -1;
}
if(write(fd,buf+4,res-4)<0)
{
ERR_MSG("write");
return -1;
}
//组ACK包
char ackbuf[4]="";
unsigned short *ps=(unsigned short *)ackbuf;
*ps=htons(4);
unsigned short *pl=(unsigned short *)(ackbuf+2);
*pl=*((unsigned short *)(buf+2));
//发送ACK包
if(sendto(cfd,ackbuf,sizeof(ackbuf),0,(struct sockaddr *)&newsin,sizeof(newsin))<0)
{
ERR_MSG("sendto");
return -1;
}
//数据小于512退出下载
if(res-4<516)
{
printf("下载成功\n");
break;
}
}
close(fd);
return 0;
}
int do_upload(int cfd,struct sockaddr_in sin)
{
char name[20]="";
printf("请输入文件名:");
scanf("%s",name);
getchar();
//组上传协议
char buf[516]="";
unsigned short *p1=(unsigned short *)buf;
*p1=htons(2);
char * p2= (char *)(p1+1);
strcpy(p2,name);
char * p3=p2+strlen(p2)+1;
strcpy(p3,"octet");
//发送上传协议给服务器
int size=2+strlen(p2)+1+strlen(p3)+1;
if(sendto(cfd,buf,size,0,(struct sockaddr *)&sin,sizeof(sin))<0)
{
ERR_MSG("sendto");
return -1;
}
printf("sendto success\n");
//接收服务器的应答
struct sockaddr_in newsin;
socklen_t len= sizeof(newsin);
recvfrom(cfd,buf,size,0,(struct sockaddr *)&newsin,&len); //接收服务器的随机端口和ip
printf("%d\n",ntohs(newsin.sin_port));
//打开读文件
int fd = open(name,O_RDONLY);
short i=0;
ssize_t res=0;
while(1)
{
bzero(buf,sizeof(buf));
//组数据包
unsigned short * pl =(unsigned short *)buf;
*pl=htons(3);
unsigned short * ps=(unsigned short *)(buf+2);
*ps=htons(++i);
char * readbuf= buf+4;
res = read(fd,readbuf,sizeof(buf)-4);
if(res<0)
{
ERR_MSG("read");
return -1;
}
//发送数据包
if(sendto(cfd,buf,sizeof(buf),0,(struct sockaddr *)&newsin,len)<0)
{
ERR_MSG("sendto");
return -1;
}
//接收服务器的应答 并判断是否正确 错误退出
char ackbuf[4]="";
if(recvfrom(cfd,ackbuf,sizeof(ackbuf),0,NULL,NULL)<0)
{
ERR_MSG("recvfrom");
return -1;
}
//判断操作码是否为4 块编号是否为i
if(*((unsigned short *)ackbuf)!=htons(4) || *((unsigned short *)(ackbuf+2))!=htons(i))
{
printf("接收应答错误\n");
break;
}
//判断上传数据是否小于512
if(res<512)
{
printf("上传完毕\n");
break;
}
}
close(fd);
return 0;
}