tftp下载:
#include <myhead.h>
#define PORT 69 //目标端口号,范围1024~49151
#define IP "192.168.114.53"//目标IP
int do_download(int cfd, struct sockaddr_in sin);
int main(int argc, const char *argv[])
{
//1、创建报式套接字
int cfd = socket(AF_INET, SOCK_DGRAM, 0);
if(cfd < 0)
{
ERR_MSG("socket");
return -1;
}
printf("socket creat success cfd=%d\n",cfd);
//填充服务器的地址信息结构体,
//真实的地址信息结构体根据地址族指定,AF_INET
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);//目标的端口号网络字节序1024-49151
sin.sin_addr.s_addr = inet_addr(IP);//目标IP
char choose = 0;
while(1)
{
system("clear");
printf("**************************\n");
printf("***********1.下载*********\n");
printf("***********2.上传*********\n");
printf("***********3.退出*********\n");
printf("**************************\n");
printf("请输入>>>");
scanf("%c",&choose);
while(getchar() != 10);//循环吸收垃圾字符
switch(choose)
{
case '1':
do_download(cfd,sin);
break;
case '2':
//do_upload()
break;
case '3'://退出
goto END;
break;
default:
printf("输入错误,请重新输入\n");
}
printf("输入任意字符清屏>>>");
while(getchar() != 10);
}
END:
//关闭
close(cfd);
return 0;
}
//下载函数
int do_download(int cfd, struct sockaddr_in sin)
{
char filename[20]="";
printf("请输入文件名>>>");
scanf("%s",filename);
while(getchar() != 10);
//组下载请求包
char buf[516] = "";
unsigned short* ptr1 = (unsigned short*)buf;//操作码
*ptr1 = htons(1);
char* ptr2 = buf+2;
strcpy(ptr2,filename);//文件名
char* ptr4 = ptr2 +strlen(filename)+1;//操作模式
strcpy(ptr4,"octet");
int size = 2+strlen(ptr2)+1+strlen(ptr4)+1;
//发送下载请求包 sendto
if(sendto(cfd, buf, size, 0, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
ERR_MSG("sendto");
return -1;
}
printf("sendto download request success\n");
int fd = -1;//定义一个文件描述符操控被写入的文件
socklen_t addrlen = sizeof(sin);
ssize_t res = 0;
unsigned short num = 0;//记录本地的块编号
while(1)
{
//接收数据 recvfrom,接收地址信息
if((res=recvfrom(cfd, buf, sizeof(buf), 0, (struct sockaddr*)&sin, &addrlen))<0)
{
ERR_MSG("recvfrom");
return -1;
}
if(3 == buf[1])//数据包
{
if(*(unsigned short*)(buf+2) == htons(num+1))
{
num++;//更新本地记录的块编号
if(-1 == fd)
{
if((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664)) < 0)
{
ERR_MSG("open");
return -1;;
}
}
//将收到的数据写入文件
if(write(fd, buf+4, res-4) < 0)
{
ERR_MSG("write");
close(fd);
return -1;
}
//发送ACK
buf[1]=4;
if(sendto(cfd, buf, 4, 0, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
ERR_MSG("sendto");
return -1;
}
if(res-4 < 512)//数据小于512 则下载完成
{
printf("%s 下载完毕\n",filename);
break;
}
}
}
else if(5 == buf[1]) //错误包
{
printf("错误: %d %s\n", ntohs(*(short*)(buf+2)), buf+4);
close(fd);
return -1;
}
}
close(fd);
return 0;
}
//int do_upload()
思维导图: