以下是一个简单的TFTP服务器端的C语言例子,可以用于向客户端提供文件下载服务:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define TFTP_PORT 69
typedef struct {
unsigned short opcode;
union {
unsigned short block_num;
unsigned short error_code;
char data[1];
} data;
} tftp_packet;
int main(int argc, char *argv[]) {
if(argc != 2) {
printf("Usage: %s <file_path>\n", argv[0]);
exit(1);
}
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd < 0) {
perror("socket");
exit(1);
}
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(TFTP_PORT);
if(bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
perror("bind");
exit(1);
}
while(1) {
tftp_packet *packet = (tftp_packet *)malloc(sizeof(tftp_packet) + 512);
socklen_t addrlen = sizeof(servaddr);
int n = recvfrom(sockfd, packet, sizeof(tftp_packet) + 512, 0, (struct sockaddr *)&servaddr, &addrlen);
if(n < 0) {
perror("recvfrom");
exit(1);
}
if(ntohs(packet->opcode) == 1) {
char *file_path = packet->data.data;
FILE *fp = fopen(file_path, "rb");
if(fp == NULL) {
packet->opcode = htons(5);
packet->data.error_code = htons(1);
sendto(sockfd, packet, sizeof(tftp_packet), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
free(packet);
continue;
}
int block_num = 1;
while(1) {
tftp_packet *packet = (tftp_packet *)malloc(sizeof(tftp_packet) + 512);
packet->opcode = htons(3);
packet->data.block_num = htons(block_num);
int n = fread(packet->data.data, 1, 512, fp);
sendto(sockfd, packet, sizeof(tftp_packet) + n, 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
while(1) {
tftp_packet *ack_packet = (tftp_packet *)malloc(sizeof(tftp_packet));
socklen_t addrlen = sizeof(servaddr);
int n = recvfrom(sockfd, ack_packet, sizeof(tftp_packet), 0, (struct sockaddr *)&servaddr, &addrlen);
if(n < 0) {
perror("recvfrom");
exit(1);
}
if(ntohs(ack_packet->opcode) == 4 && ntohs(ack_packet->data.block_num) == block_num) {
block_num++;
break;
}
}
if(n < 512) {
break;
}
}
fclose(fp);
}
free(packet);
}
close(sockfd);
return 0;
}
该例子中,服务器端接收到客户端的读请求后,会打开指定的文件,并将文件内容分块发送给客户端。服务器端需要等待客户端的确认包,以确认客户端已经接收到数据包。如果客户端返回错误信息,则服务器端需要发送错误信息给客户端。
【最后一个bug】多平台都有更新和发布,大家可以一键三连,关注+星标,不错过精彩内容~~