嵌入式学习——3——UDP TFTP简易文件传输

慈云数据 6个月前 (05-28) 技术支持 26 0

tftp协议概述

简单文件传输协议,适用于在网络上进行文件传输的一套标准协议,使用UDP传输

特点:

        是应用层协议

        基于UDP协议实现

数据传输模式

        octet:二进制模式(常用)

        mail:已经不再支持

TFTP通信过程总结

  1. 服务器在69号端口等待客户端的请求
  2. 服务器若批准此请求,则使用 临时端口 与客户端进行通信。
  3. 每个数据包的编号都有变化(从1开始)
  4. 每个数据包都要得到ACK的确认,如果出现超时,则需要重新发送最后的数据包或ACK包
  5. 数据长度以512Byte传输的,小于512Byte的数据意味着数据传输结束

TFTP协议分析

差错码:

0 未定义,差错错误信息

1 File not found.

2 Access violation.

3 Disk full or allocation exceeded.

4 illegal TFTP operation.

5 Unknown transfer ID.

6 File already exists.

7 No such user.

8 Unsupported option(s) requested.

#include "../header.h"
#define S_IP "192.168.125.30"
#define S_PORT 69
typedef struct file_header {
    int size;
    char *file_report;
} file_header_report;
char buf[516] = "";
char fileName[128] = {0};
int sockfd = -1;
int data_num = 0;
void download_file(struct sockaddr_in *addr);
void upload_file(struct sockaddr_in *addr);
void dealerror(short errno);
file_header_report get_report_RW(short type);
file_header_report get_report_ACK(short type, short blknumber);
int main(int argc, char const *argv[]) {
    // 服务器地址 ,初始地址用于链接请求,但是不是用于实际数据交互
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(S_PORT);
    addr.sin_addr.s_addr = inet_addr(S_IP);
    char choose = 0;
    while (1) {
        printf("**************************\n");
        printf("******** 1. 下载 *********\n");
        printf("******** 2. 上传 *********\n");
        printf("******** 3. 退出 *********\n");
        printf("**************************\n");
        printf("请输入>>> ");
        choose = getchar();
        while (getchar() != 10) {
        };
        switch (choose) {
        case '1':
            download_file(&addr);
            break;
        case '2':
            upload_file(&addr);
            break;
        case '3':
            exit(EXIT_SUCCESS);
            break;
        default:
            printf("输入错误!请重新输入\n");
        }
    }
    close(sockfd);
    return 0;
}
void upload_file(struct sockaddr_in *addr) {
    if (sockfd == -1) { // 判断一下,防止重复创建套接字
        sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd  4) {
                write(download_fd, buf + 4, read_size - 4);
            }
            // 发送ACK
            *first_no = htons(4);
            char newbuf[4] = {0};
            short *p1 = (short *)newbuf;
            *p1 = htons(4);
            short *p2 = (short *)(newbuf + 2);
            *p2 = *blk_num;
            if (sendto(sockfd, newbuf, 4, 0, (struct sockaddr *)&recv_addr,
                       sizeof(recv_addr)) == -1) {
                perror("sendtoACK\n");
            }
            printf("发送ACK成功\n");
            if (read_size  1) {
        fileName[strlen(fileName) - 1] = '\0';
    }
    short *p1 = (short *)buf;
    *p1 = htons(type);
    char *p2 = buf + 2;
    strcpy(p2, fileName);
    char *p4 = p2 + strlen(p2) + 1;
    strcpy(p4, "octet");
    int size = 2 + strlen(p2) + strlen(p4) + 2;
    file_header_report fh = {size, buf};
    return fh;
}
微信扫一扫加客服

微信扫一扫加客服

点击启动AI问答
Draggable Icon