基于UDP的TFTP文件上传
#include <myhead.h>
#define PORT 69
#define IP "192.168.125.59"
int down(const char *);
int up(const char *);
int main(int argc, const char *argv[])
{
while(1){
system("clear");
puts("***************功能**************");
puts("*************1. 下载*************");
puts("*************2. 上传*************");
puts("*************3. 退出*************");
int choose = -1;
char filename[128] = "";
scanf("%d", &choose);
switch(choose){
case 1:
{
printf("输入文件名>>");
scanf(" %[^\n]", filename);
if(down(filename) == -1){
return -1;
}
}
break;
case 2:
{
printf("输入文件名>>");
scanf(" %[^\n]", filename);
if(up(filename) == -1){
return -1;
}
}
break;
case 3:
return 0;
default:
puts("输入错误");
}
}
return 0;
}
int down(const char *filename){
int cfd = socket(AF_INET, SOCK_DGRAM, 0);
if(cfd == -1){
perror("socket error");
return -1;
}
char buf[516];
bzero(buf, sizeof(buf));
buf[1] = 1;
strcpy(buf+2, filename);
char mod[6] = "octet";
strcpy(buf+2+strlen(filename)+1, mod);
int size = 2+strlen(filename)+1+strlen(mod)+1;
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
socklen_t socklen = sizeof(sin);
if(sendto(cfd, buf, size, 0, (struct sockaddr *)&sin, sizeof(sin)) == -1){
perror("sendto error");
return -1;
}
puts("请求成功");
int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664);
while(1){
bzero(buf, sizeof(buf));
int res = -1;
if((res = recvfrom(cfd, buf, sizeof(buf), 0, (struct sockaddr *)&sin, &socklen)) == -1){
perror("recvfrom error");
return -1;
}
if(buf[1] == 3){
if(res < 516){
write(fd, buf+4, res-4);
buf[1] = 4;
sendto(cfd, buf, 4, 0, (struct sockaddr *)&sin, sizeof(sin));
break;
}else{
write(fd, buf+4, 512);
buf[1] = 4;
sendto(cfd, buf, 4, 0, (struct sockaddr *)&sin, sizeof(sin));
}
}else{
printf("未知错误,错误码: %d\n", buf[3]);
close(fd);
close(cfd);
return -1;
}
}
close(fd);
close(cfd);
return 0;
}
int up(const char *filename){
int cfd = socket(AF_INET, SOCK_DGRAM, 0);
if(cfd == -1){
perror("socket error");
return -1;
}
char buf[516];
bzero(buf, sizeof(buf));
buf[1] = 2;
strcpy(buf+2, filename);
char mod[6] = "octet";
strcpy(buf+2+strlen(filename)+1, mod);
int size = 2+strlen(filename)+1+strlen(mod)+1;
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
socklen_t socklen = sizeof(sin);
if(sendto(cfd, buf, size, 0, (struct sockaddr *)&sin, sizeof(sin)) == -1){
perror("sendto error");
return -1;
}
puts("请求成功");
int fd = open(filename, O_RDONLY);
short block_num = 0;
short * const p = (short *)(buf+2);
int res = -1;
while(1){
recvfrom(cfd, buf, 4, 0, (struct sockaddr *)&sin, &socklen);
if(buf[1] == 4){
if(ntohs(*p) == 0 || block_num == ntohs(*p)){
buf[1] = 3;
res = read(fd, buf+4, 512);
*p = htons(++block_num);
size = res + 4;
if(res == 0){
break;
}else{
sendto(cfd, buf, size, 0, (struct sockaddr *)&sin, sizeof(sin));
}
}else{
buf[1] = 3;
sendto(cfd, buf, size, 0, (struct sockaddr *)&sin, sizeof(sin));
}
}else{
printf("未知错误,错误码: %d\n", buf[3]);
close(fd);
close(cfd);
return -1;
}
}
close(fd);
close(cfd);
return 0;
}

思维导图
