#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PORT 69
#define IP "192.168.122.87"
#define FINENAME "1_armcli.c"
int main(int argc, const char *argv[])
{
//创建报式套接字
int cfd = socket(AF_INET,SOCK_DGRAM,0);
if(cfd < 0)
{
perror("socket");
return -1;
}
printf("socket success...\n");
//填充服务器地址信息结构体
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
//读写请求
char buf[516] = "";
//操作码
unsigned short *p1 = (unsigned short *)buf;
*p1 = htons(1);
//文件名
char *p2 = buf+2;
strcpy(p2,FINENAME);
//0
char *p3 = p2+strlen(p2);
*p3 = 0;
//模式
char *p4 = p3+1;
strcpy(p4,"octet");
//发送读写请求
if(sendto(cfd,buf,2+strlen(p2)+1+strlen(p4)+1,0,(struct sockaddr *)&sin,sizeof(sin)) < 0)
{
perror("sendto");
return -1;
}
ssize_t res = 0;
socklen_t addrlen = sizeof(sin);
unsigned short num = 1; //块编号
int fd = -1; //定义本地下载文件描述符
while(1)
{
//接收数据包
bzero(buf,sizeof(buf));
res = recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr *)&sin,&addrlen);
if(res < 0)
{
perror("recvfrom");
return -1;
}
//判断块编号,避免数据包重复
if(3 == ntohs(*(unsigned short *)buf))
{
if(htons(num) == *(unsigned short *)(buf+2))
{
num++;
if(-1 == fd)
{
fd = open(FINENAME,O_WRONLY|O_CREAT|O_TRUNC,0664);
if(fd < 0)
{
perror("open");
break;
}
}
if(write(fd,buf+4,res-4) < 0)
{
perror("write");
return -1;
}
//回复ACK
*(unsigned short *)buf = htons(4);
if(sendto(cfd,buf,4,0,(struct sockaddr *)&sin,sizeof(sin)) < 0)
{
perror("sendto");
return -1;
}
//数据包小于512,结束
if(res - 4 < 512)
{
printf("download success\n");
break;
}
}
}
else if(5 == ntohs(*(unsigned short *)buf))
{
printf("%s\n",buf+4);
break;
}
}
//关闭文件描述符
close(fd);
close(cfd);
return 0;
}
TFTP协议下载实验
猜你喜欢
转载自blog.csdn.net/weixin_53478812/article/details/132258448
今日推荐
周排行