From ce8809301171cfc8349e85d4807d669cc7c808e6 Mon Sep 17 00:00:00 2001 From: flykhan Date: Wed, 6 Sep 2023 14:26:36 +0800 Subject: [PATCH] =?UTF-8?q?tftp=E6=96=87=E4=BB=B6=E6=8E=A5=E6=94=B6?= =?UTF-8?q?=E5=AE=A2=E6=88=B7=E7=AB=AFv1,v2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- day3/tftpc.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++ day3/tftpc_2.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 177 insertions(+) create mode 100644 day3/tftpc.c create mode 100644 day3/tftpc_2.c diff --git a/day3/tftpc.c b/day3/tftpc.c new file mode 100644 index 0000000..c5a548e --- /dev/null +++ b/day3/tftpc.c @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* +* ./a.out server_ip 下载的文件名 +* ./tftpc server_ip filename +*/ + +int main(int argc, char const *argv[]) +{ + if (argc < 3) + { + printf("usage: %s server_ip filename\n", argv[0]); + return 1; + } + + int sock_fd = socket(AF_INET, SOCK_DGRAM, 0); + if (sock_fd < 0) + { + perror("socket"); + return -1; + } + + // 生成请求报文(数据包) + char request[64]; + sprintf(request, "%c%c%s%c%s%c", + 0, 1, argv[2], 0, "octet", 0); + // 发送请求 + struct sockaddr_in server_addr; + bzero(&server_addr, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(69); // TFTP 端口号 + server_addr.sin_addr.s_addr = inet_addr(argv[1]); + + size_t request_size = strlen(argv[2]) + 9; + sendto(sock_fd, request, request_size, 0, (struct sockaddr *)&server_addr, sizeof(server_addr)); + + // 创建本地文件的描述符(打开或创建文件) + int file_fd = open(argv[2], O_CREAT | O_WRONLY, 0666); + + while (1) + { + char buf[516] = ""; + struct sockaddr_in data_addr; + // bzero(&data_addr, sizeof(data_addr)); + socklen_t data_addr_len = sizeof(data_addr); + + ssize_t recv_len = recvfrom(sock_fd, buf, 516, 0, (struct sockaddr *)&data_addr, &data_addr_len); + + // 判断接收的数据是否 OK + if (buf[1] == 3) + { + printf("ok: %d -> %s\n", *(buf + 3), buf + 4); + // 收到的是数据包 + write(file_fd, buf + 4, recv_len - 4); + + // 回 ACK "Acknowledgment"(确认) + buf[1] = 4; + sendto(sock_fd, buf, 4, 0, (struct sockaddr *)&data_addr, data_addr_len); + } + else if (buf[1] == 5) + { + // 收到的是错误信息包 + printf("error: %d -> %s\n", *(buf + 3), buf + 4); + execlp("rm", "rm", "-rf", argv[2], NULL); + } + else if (buf[1] == 6) + { + // 收到的是 OACK 包,包含请求选项回传的值 + } + + if (recv_len < 516) + { + printf("数据接收完成\n"); + break; // 接到最后一组数据后不再接收 + } + } + + close(file_fd); + close(sock_fd); + + return 0; +} diff --git a/day3/tftpc_2.c b/day3/tftpc_2.c new file mode 100644 index 0000000..8c9b3e5 --- /dev/null +++ b/day3/tftpc_2.c @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * ./a.out server_ip 下载的文件名 + * ./tftpc server_ip filename + */ +int main(int argc, char const *argv[]) +{ + if (argc < 3) + { + printf("format: %s server_ip filename\n", argv[0]); + return -1; + } + + int sock_fd = socket(AF_INET, SOCK_DGRAM, 0); + if (sock_fd < 0) + { + perror("socket"); + return -1; + } + // 生成请求数据包 + char request[64]; + int request_size = sprintf(request, "%c%c%s%c%s%c", 0, 1, argv[2], 0, "octet", 0); + + // 发送请求 + struct sockaddr_in server_addr; + bzero(&server_addr, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(69); + server_addr.sin_addr.s_addr = inet_addr(argv[1]); + + sendto(sock_fd, request, request_size, 0, (struct sockaddr *)&server_addr, sizeof(server_addr)); + + char buf[516] = ""; + struct sockaddr_in data_addr; + socklen_t data_addr_len = sizeof(data_addr); + bzero(&data_addr, data_addr_len); + ssize_t len = recvfrom(sock_fd, buf, 516, 0, (struct sockaddr *)&data_addr, &data_addr_len); + + // 验证接收的数据是否OK + if (buf[1] == 3) + { + // 创建本地文件的描述符(打开或创建文件) + int fd = open(argv[2], O_CREAT | O_WRONLY, 0666); + + while (1) + { + // 收到的是数据包 + write(fd, buf + 4, len - 4); + // 回ACK + buf[1] = 4; + sendto(sock_fd, buf, 4, 0, (struct sockaddr *)&data_addr, sizeof(data_addr)); + if (len < 516) + { + printf("数据接收完成\n"); + break; + } + + bzero(&data_addr, data_addr_len); + bzero(buf, sizeof(buf)); + len = recvfrom(sock_fd, buf, 516, 0, (struct sockaddr *)&data_addr, &data_addr_len); + } + + close(fd); + } + else if (buf[1] == 5) + { + // 收到的错误信息包 + printf("error: %s\n", buf + 4); + } + else if (buf[1] == 6) + { + // 收到的OACK包,包含请求选项回传的值 + } + + close(sock_fd); + return 0; +} \ No newline at end of file