一,替换system直接写入
#include <stdlib.h>
#include <stdio.h>
int main()
{
char user_input[100];
printf("请输入一个字符串: ");
fgets(user_input, sizeof(user_input), stdin);
// 去除换行符
user_input[strcspn(user_input, "\n")] = 0;
char command[200];
sprintf(command, "echo \"%s\"", user_input);
system(command);
return 0;
}
二,替换tftp
1,tftp.h
#ifndef _TFTP_H_
#define _TFTP_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#define TFTP_PORT 69
#define BUFFER_SIZE 516
#define DATA_SIZE 512
#define TIMEOUT 5
// TFTP 操作码
#define RRQ 1
#define WRQ 2
#define DATA 3
#define ACK 4
#define ERROR 5
// TFTP 错误码
#define NOT_DEFINED 0
#define FILE_NOT_FOUND 1
#define ACCESS_VIOLATION 2
#define DISK_FULL 3
#define ILLEGAL_OPERATION 4
#define UNKNOWN_TID 5
#define FILE_EXISTS 6
#define NO_SUCH_USER 7
struct tftp_packet
{
uint16_t opcode;
union {
struct {
char filename[2];
} rrq_wrq;
struct {
uint16_t block_num;
char data[DATA_SIZE];
} data;
struct {
uint16_t block_num;
} ack;
struct {
uint16_t error_code;
char error_msg[2];
} error;
};
};
// 打印使用说明
void print_usage(const char *program_name);
// 创建 TFTP 请求包
int create_request_packet(char *buffer, uint16_t opcode, const char *filename, const char *mode);
// 创建数据包
int create_data_packet(char *buffer, uint16_t block_num, const char *data, int data_len);
// 创建 ACK 包
int create_ack_packet(char *buffer, uint16_t block_num);
// 创建错误包
int create_error_packet(char *buffer, uint16_t error_code, const char *error_msg);
// 解析收到的包
int parse_packet(const char *buffer, int len, uint16_t *opcode, uint16_t *block_num, char *data, int *data_len, uint16_t *error_code, char *error_msg) ;
// 下载文件 (GET)
int tftp_get(const char *server, const char *remote_file, const char *local_file);
// 上传文件 (PUT)
int tftp_put(const char *server, const char *local_file, const char *remote_file);
#endif
2,tftp.c
#include"tftp.h"
// 打印使用说明
void print_usage(const char *program_name)
{
printf("Usage: %s [get|put] <remote_filename> [local_filename]\n", program_name);
printf("Examples:\n");
printf(" %s get remote.txt local.txt\n", program_name);
printf(" %s put local.txt remote.txt\n", program_name);
printf(" %s get remote.txt (uses same local filename)\n", program_name);
}
// 创建 TFTP 请求包
int create_request_packet(char *buffer, uint16_t opcode, const char *filename, const char *mode) {
uint16_t *op = (uint16_t *)buffer;
*op = htons(opcode);
char *ptr = buffer + 2;
strcpy(ptr, filename);
ptr += strlen(filename) + 1;
strcpy(ptr, mode);
ptr += strlen(mode) + 1;
return ptr - buffer;
}
// 创建数据包
int create_data_packet(char *buffer, uint16_t block_num, const char *data, int data_len) {
uint16_t *op = (uint16_t *)buffer;
*op = htons(DATA);
uint16_t *block = (uint16_t *)(buffer + 2);
*block = htons(block_num);
memcpy(buffer + 4, data, data_len);
return data_len + 4;
}
// 创建 ACK 包
int create_ack_packet(char *buffer, uint16_t block_num) {
uint16_t *op = (uint16_t *)buffer;
*op = htons(ACK);
uint16_t *block = (uint16_t *)(buffer + 2);
*block = htons(block_num);
return 4;
}
// 创建错误包
int create_error_packet(char *buffer, uint16_t error_code, const char *error_msg) {
uint16_t *op = (uint16_t *)buffer;
*op = htons(ERROR);
uint16_t *error = (uint16_t *)(buffer + 2);
*error = htons(error_code);
strcpy(buffer + 4, error_msg);
return strlen(error_msg) + 5;
}
// 解析收到的包
int parse_packet(const char *buffer, int len, uint16_t *opcode, uint16_t *block_num,
char *data, int *data_len, uint16_t *error_code, char *error_msg) {
if (len < 2) return -1;
*opcode = ntohs(*(uint16_t *)buffer);
switch (*opcode) {
case DATA:
if (len < 4) return -1;
*block_num = ntohs(*(uint16_t *)(buffer + 2));
*data_len = len - 4;
if (data && *data_len > 0) {
memcpy(data, buffer + 4, *data_len);
}
break;
case ACK:
if (len < 4) return -1;
*block_num = ntohs(*(uint16_t *)(buffer + 2));
break;
case ERROR:
if (len < 4) return -1;
*error_code = ntohs(*(uint16_t *)(buffer + 2));
if (error_msg && len > 4) {
strncpy(error_msg, buffer + 4, len - 4);
error_msg[len - 4] = '\0';
}
break;
default:
return -1;
}
return 0;
}
// 下载文件 (GET)
int tftp_get(const char *server, const char *remote_file, const char *local_file) {
int sockfd;
struct sockaddr_in server_addr, client_addr;
socklen_t addr_len = sizeof(server_addr);
char buffer[BUFFER_SIZE];
char data_buffer[DATA_SIZE];
int fd, ret;
// 创建 socket
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("socket");
return -1;
}
// 设置服务器地址
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(TFTP_PORT);
if (inet_pton(AF_INET, server, &server_addr.sin_addr) <= 0) {
// 尝试解析主机名
struct hostent *he = gethostbyname(server);
if (he == NULL)
{
fprintf(stderr, "Error: Cannot resolve hostname '%s'\n", server);
close(sockfd);
return -1;
}
memcpy(&server_addr.sin_addr, he->h_addr_list[0], he->h_length);
}
// 创建本地文件
fd = open(local_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd < 0) {
perror("open");
close(sockfd);
return -1;
}
// 发送读请求
int packet_len = create_request_packet(buffer, RRQ, remote_file, "octet");
ret = sendto(sockfd, buffer, packet_len, 0,
(struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret < 0) {
perror("sendto");
close(fd);
close(sockfd);
return -1;
}
printf("Downloading %s from %s to %s\n", remote_file, server, local_file);
uint16_t expected_block = 1;
int total_bytes = 0;
// 设置超时
struct timeval tv;
tv.tv_sec = TIMEOUT;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
while (1)
{
int n = recvfrom(sockfd, buffer, BUFFER_SIZE, 0,
(struct sockaddr *)&server_addr, &addr_len);
if (n < 0)
{
if (errno == EAGAIN || errno == EWOULDBLOCK) {
fprintf(stderr, "Timeout waiting for data\n");
break;
}
perror("recvfrom");
break;
}
uint16_t opcode, block_num, error_code;
int data_len;
char error_msg[256];
if (parse_packet(buffer, n, &opcode, &block_num, data_buffer, &data_len,
&error_code, error_msg) < 0)
{
fprintf(stderr, "Error: Invalid packet received\n");
break;
}
if (opcode == ERROR)
{
fprintf(stderr, "TFTP Error %d: %s\n", error_code, error_msg);
break;
}
if (opcode == DATA) {
if (block_num == expected_block) {
// 写入数据
write(fd, data_buffer, data_len);
total_bytes += data_len;
// 发送 ACK
packet_len = create_ack_packet(buffer, block_num);
sendto(sockfd, buffer, packet_len, 0,
(struct sockaddr *)&server_addr, sizeof(server_addr));
printf("\rReceived %d bytes...", total_bytes);
fflush(stdout);
// 检查是否结束
if (data_len < DATA_SIZE) {
printf("\nDownload completed: %d bytes\n", total_bytes);
break;
}
expected_block++;
} else if (block_num == expected_block - 1) {
// 重复包,重新发送 ACK
packet_len = create_ack_packet(buffer, block_num);
sendto(sockfd, buffer, packet_len, 0,
(struct sockaddr *)&server_addr, sizeof(server_addr));
}
}
}
close(fd);
close(sockfd);
return total_bytes > 0 ? 0 : -1;
}
// 上传文件 (PUT)
int tftp_put(const char *server, const char *local_file, const char *remote_file) {
int sockfd;
struct sockaddr_in server_addr, client_addr;
socklen_t addr_len = sizeof(server_addr);
char buffer[BUFFER_SIZE];
char data_buffer[DATA_SIZE];
int fd, ret;
// 创建 socket
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("socket");
return -1;
}
// 设置服务器地址
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(TFTP_PORT);
if (inet_pton(AF_INET, server, &server_addr.sin_addr) <= 0) {
struct hostent *he = gethostbyname(server);
if (he == NULL) {
fprintf(stderr, "Error: Cannot resolve hostname '%s'\n", server);
close(sockfd);
return -1;
}
memcpy(&server_addr.sin_addr, he->h_addr_list[0], he->h_length);
}
// 打开本地文件
fd = open(local_file, O_RDONLY);
if (fd < 0) {
perror("open");
close(sockfd);
return -1;
}
// 发送写请求
int packet_len = create_request_packet(buffer, WRQ, remote_file, "octet");
ret = sendto(sockfd, buffer, packet_len, 0,
(struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret < 0) {
perror("sendto");
close(fd);
close(sockfd);
return -1;
}
printf("Uploading %s to %s as %s\n", local_file, server, remote_file);
uint16_t current_block = 0;
int total_bytes = 0;
int bytes_read;
// 设置超时
struct timeval tv;
tv.tv_sec = TIMEOUT;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
while (1) {
// 等待 ACK
int n = recvfrom(sockfd, buffer, BUFFER_SIZE, 0,
(struct sockaddr *)&server_addr, &addr_len);
if (n < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
fprintf(stderr, "Timeout waiting for ACK\n");
break;
}
perror("recvfrom");
break;
}
uint16_t opcode, block_num, error_code;
char error_msg[256];
if (parse_packet(buffer, n, &opcode, &block_num, NULL, NULL,
&error_code, error_msg) < 0) {
fprintf(stderr, "Error: Invalid packet received\n");
break;
}
if (opcode == ERROR) {
fprintf(stderr, "TFTP Error %d: %s\n", error_code, error_msg);
break;
}
if (opcode == ACK) {
if (block_num == current_block) {
current_block++;
// 读取文件数据
bytes_read = read(fd, data_buffer, DATA_SIZE);
if (bytes_read < 0) {
perror("read");
break;
}
total_bytes += bytes_read;
// 发送数据包
packet_len = create_data_packet(buffer, current_block, data_buffer, bytes_read);
ret = sendto(sockfd, buffer, packet_len, 0,
(struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret < 0) {
perror("sendto");
break;
}
printf("\rSent %d bytes...", total_bytes);
fflush(stdout);
// 检查是否结束
if (bytes_read < DATA_SIZE) {
// 等待最后一个 ACK
n = recvfrom(sockfd, buffer, BUFFER_SIZE, 0,
(struct sockaddr *)&server_addr, &addr_len);
if (n > 0) {
parse_packet(buffer, n, &opcode, &block_num, NULL, NULL,
&error_code, error_msg);
if (opcode == ACK && block_num == current_block) {
printf("\nUpload completed: %d bytes\n", total_bytes);
}
}
break;
}
}
}
}
close(fd);
close(sockfd);
return total_bytes > 0 ? 0 : -1;
}
3,main.c
#include"tftp.h"
int main(int argc, char *argv[])
{
if (argc < 4)
{
print_usage(argv[0]);
return 1;
}
const char *operation = argv[1];
const char *remote_file = argv[2];
const char *local_file = (argc > 3) ? argv[3] : remote_file;
// 从环境变量获取服务器地址,默认为 localhost
const char *server = getenv("TFTP_SERVER");
if (server == NULL)
{
server = "127.0.0.1";
}
if (strcmp(operation, "get") == 0)
{
// return tftp_get(server, remote_file, local_file);
printf("+++%d\n",tftp_get(server, remote_file, local_file));
}
else if (strcmp(operation, "put") == 0)
{
// return tftp_put(server, local_file, remote_file);
printf("---%d\n",tftp_put(server, local_file, remote_file) );
}
else
{
fprintf(stderr, "Error: Unknown operation '%s'\n", operation);
print_usage(argv[0]);
return 1;
}
return 0;
}
./mytftp
Usage: ./mytftp [get|put] <remote_filename> [local_filename]
Examples:
./mytftp get remote.txt local.txt
./mytftp put local.txt remote.txt
./mytftp get remote.txt (uses same local filename)

被折叠的 条评论
为什么被折叠?



