qfedu-network-advanced-level/day3/tftpc_2.c

86 lines
2.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
/**
* ./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;
}