实现基于UDP的TFTP文件传输;
#include "../include/head.h"
void download_file(int sockfd, struct sockaddr_in addr) {
char buf[516] = {0};
char file_name[128];
printf("输入文件名:");
scanf("%s", file_name);
char mode[] = "octet";
snprintf(buf, sizeof(buf), "%c%c%s%c%s%c", 0, 1,file_name,0,mode,0);
//发送下载请求
if (sendto(sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
perror("sendto error");
return;
}
int fd = open(file_name, O_TRUNC | O_CREAT | O_RDWR, 0664);
if (fd == -1) {
perror("open error");
return;
}
struct sockaddr_in server_addr;
socklen_t server_addr_len = sizeof(server_addr);
uint16_t code;
uint16_t num = 1;
printf("发送下载请求成功\n");
while (1) {
memset(buf, 0, sizeof(buf));
int ret = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&server_addr, &server_addr_len);
if (ret == -1) {
perror("recv error");
close(fd);
return;
}
code = ntohs(*(short*)(buf + 2));
if (buf[1] == 3) {
if (num == code) {
int write_size = write(fd, buf + 4, ret - 4);
num++;
buf[1] = 4;
sendto(sockfd, buf, 4, 0, (struct sockaddr*)&server_addr, server_addr_len);
if (ret < 516) {
printf("下载完成...\n");
break;
}
}
} else if (buf[1] == 5) {
printf("[%d]:错误信息:%s\n", code, buf + 4);
break;
}
}
close(fd);
}
void upload_file(int sockfd, struct sockaddr_in addr) {
char buf[516] = {0};
char file_name[128];
printf("输入文件名:");
scanf("%s", file_name);
char mode[] = "octet";
snprintf(buf, sizeof(buf), "%c%c%s%c%s%c", 0, 2,file_name,0,mode,0);
//发送上传请求
if (sendto(sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
perror("sendto error");
return;
}
int fd = open(file_name, O_RDONLY);
if (fd == -1) {
perror("open error");
return;
}
struct sockaddr_in server_addr;
socklen_t server_addr_len = sizeof(server_addr);
uint16_t code;
uint16_t num = 0;
printf("发送上传请求成功\n");
while (1) {
memset(buf, 0, sizeof(buf));
int ret = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&server_addr, &server_addr_len);
if (ret == -1) {
perror("recv error");
close(fd);
return;
}
code = ntohs(*(short*)(buf + 2));
if (buf[1] == 4) {
ret = read(fd, buf + 4, sizeof(buf) - 4);
if (ret < 0) {
perror("read error");
close(fd);
return;
} else if (ret == 0) {
printf("读到文件结尾...\n");
break;
} else {
buf[1] = 3;
buf[3]++;
sendto(sockfd, buf, ret + 4, 0, (struct sockaddr*)&server_addr, server_addr_len);
if (ret < sizeof(buf) - 4) {
printf("上传成功...\n");
break;
} else {
printf("发送成功...\n");
}
}
} else if (buf[1] == 5) {
printf("[%d]:错误信息:%s\n", code, buf + 4);
break;
}
}
close(fd);
}
int main(int argc, const char* argv[]) {
int client_fd;
if ((client_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("socket error");
exit(EXIT_FAILURE);
}
struct sockaddr_in client_addr;
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(69);
inet_pton(AF_INET, "192.168.199.1", &client_addr.sin_addr);
int client_len = sizeof(client_addr);
int choice, flag = 0;
while(1) {
printf("*****输入你的选择******\n");
printf("*****1、下载文件******\n");
printf("*****2、上传文件******\n");
printf("*****3、退出******\n");
scanf("%d", &choice);
switch(choice) {
case 1:
download_file(client_fd, client_addr);
break;
case 2:
upload_file(client_fd, client_addr);
break;
case 3:
flag = 1;
break;
default:
printf("输入有误!\n");
break;
}
if (flag) break;
}
close(client_fd);
return 0;
}