基于UDP的tftp客户端的下载
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PORT 69
#define IP "192.168.10.102"
int main(int argc, const char *argv[])
{
int fd = open("./copy.png",O_WRONLY|O_CREAT|O_TRUNC,0664);
if(fd < 0)
{
perror("open");
return -1;
}
//创建报式套接字
int cfd = socket(AF_INET,SOCK_DGRAM,0);
if(cfd < 0)
{
perror("socket");
return -1;
}
printf("socket create success cfd = %d\n",cfd);
//填充服务器的地址信息结构体,AF_INET;man 7 ip
//给下面的sendto函数使用
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
socklen_t len = sizeof(sin);
//组下载请求协议
char buf[516] = "";
short *ptr1 = (short *)buf;
*ptr1 = htons(1); //操作码,下载
char *ptr2 = buf + 2;
strcpy(ptr2,"5.png"); //要下载的文件名
char *ptr3 = ptr2 + strlen(ptr2);
*ptr3 = 0; //此处可以不写,因strcpy后会自动补零
char *ptr4 = ptr3 + 1;
strcpy(ptr4,"octet");
int size = 2+strlen(ptr2)+strlen(ptr4)+1;
//发送下载请求包给服务器
if(sendto(cfd,buf,size,0,(struct sockaddr *)&sin,sizeof(sin)) < 0)
{
perror("sendto");
return -1;
}
printf("发送成功\n");
//数据包
bzero(buf,sizeof(buf));
short *data1 = (short *)buf;
short *data2 = data1 + 1;
char *data3 = buf + 4;
//ACK
char res[4] = "";
short *ack1 = (short *)res;
*ack1 = htons(4);
short *ack2 = ack1 + 1;
//错误信息
char err[128] = "";
short *err1 = (short *)err;
*err1 = htons(5);
short *err2 = err1 + 1;
char *err3 = buf + 4;
ssize_t res1 = 0;
int i = 0;
while(1)
{
i++;
*data2 = htons(i);
res1 = recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr *)&sin,&len);
if(res1 < 0)
{
perror("recvfrom");
return -1;
}
write(fd,data3,res1-4);
*ack2 = htons(i);
if(sendto(cfd,res,sizeof(res),0,(struct sockaddr *)&sin,sizeof(sin)) < 0)
{
perror("sendto");
return -1;
}
printf("发送成功\n");
if(res1-4 < 512)
break;
}
return 0;
}