通过TFT通信协议实现一个服务器,可以为客户端提供文件下载(附代码)

以下是一个简单的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】多平台都有更新和发布,大家可以一键三连,关注+星标,不错过精彩内容~~在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值