当前位置: 首页 > news >正文

【网络编程】基于UDP的TFTP文件传输

1)tftp协议概述

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

特点:

是应用层协议

基于UDP协议实现

数据传输模式

octet:二进制模式(常用)

mail:已经不再支持

2)tftp下载模型

TFTP通信过程总结

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

 

代码实现

main.c

#include"tftp.h"int main(int argc, const char *argv[])
{int cmd  = 0;//用来标记操作char filename[20] = "";//存放文件名int cfd = socket(AF_INET,SOCK_DGRAM,0);//创建套接字文件if(cfd == -1){perror("socket error");return -1;}while(1){menu();printf("请输入要执行的操作:");scanf("%d",&cmd);switch(cmd){case 1:printf("请输入文件名:");scanf("%s",filename);download(cfd,filename);break;case 2:printf("请输入文件名:");scanf("%s",filename);upload(cfd,filename);break;case 3:printf("退出\n");goto END;break;default:printf("输入错误\n");break;}}
END://关闭文件描述符close(cfd);return 0;
}

tftp.c

#include"tftp.h"
//菜单
void menu()
{printf("-------------------------\n");printf("--------1.下载文件--------\n");printf("--------2.上传文件--------\n");printf("--------3.退出------------\n");printf("-------------------------\n");
}//上传
int upload(int cfd , char *filename)
{char buf[N] = "";short *p1 = (short*)buf;*p1 = htons(2);//设置操作码为2,表示上传char *p2 = buf + 2;//文件名的起始位置strcpy(p2,filename);char *p4 = p2 + strlen(p2) + 1;//模式的起始位置strcpy(p4,"octet");int size = 2 + strlen(p2) + strlen(p4) + 2;//计算请求包的总长度//打开本地文件int fd = open(filename,O_RDONLY);if(fd == -1){perror("open error");return -1;}//绑定服务器地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(SER_PORT);sin.sin_addr.s_addr = inet_addr(SER_IP);socklen_t len = sizeof(sin);//给服务段发送请求if(sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin)) == -1){perror("sendto error");return -1;}	short flag = 1;//设置标示位//收发数据while(1){//清空数据bzero(buf,sizeof(buf));if(recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&len)==-1){perror("recvfrom error");return -1;}//将ack改造成为数据包if(buf[1] == 4 || flag == buf[2]){int res = read(fd,buf+4,sizeof(buf)-4);//从buf的5个开始放数据,读取buf-4个数据if(res < 0){perror("read error");return -1;}if(res == 0){printf("文件发送完毕\n");return -1;}buf[1]=3;buf[3] = flag;if(sendto(cfd,buf,res+4,0,(struct sockaddr*)&sin,sizeof(sin)) == -1){perror("sendto error");return -1;}	flag++;}if(buf[1] == 5){printf("接收错误\n");break;}}
}//下载
int download(int cfd ,char *filename)
{char buf[N] = "";short *p1 = (short*)buf;*p1 = htons(1);//设置操作码为1,表示下载char *p2 = buf + 2;//文件名的起始位置strcpy(p2,filename);char *p4 = p2 + strlen(p2) + 1;//模式的起始位置strcpy(p4,"octet");int size = 2 + strlen(p2) + strlen(p4) + 2;//计算请求包的总长度//创建本地文件int fd = open(filename,O_CREAT|O_WRONLY|O_TRUNC,0644);if(fd == -1){perror("open error");return -1;}//绑定服务器地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(SER_PORT);sin.sin_addr.s_addr = inet_addr(SER_IP);socklen_t len = sizeof(sin);//给服务段发送请求if(sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin)) == -1){perror("sendto error");return -1;}	short flag = 1;//设置标示位while(1){//清空bzero(buf,sizeof(buf));//获取服务器发来的包int res = recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&len);if(res == -1){perror("recvfrom error");return -1;}//判断是否是数据包if(buf[1] == 3 && flag == ntohs(*(short*)(buf+2))){//将数据写入文件中if(write(fd,buf+4,N-4)==-1){perror("write error");return -1;}//返回ackbuf[1] = 4; if(sendto(cfd,buf,4,0,(struct sockaddr*)&sin,sizeof(sin))==-1){perror("sendto error");return -1;}flag++;//确保和需要的块编号一致}//判断是否是错误包if(buf[1] == 5){printf("文件发送错误\n");}//判断是否发送完毕if(res < 516){printf("文件接收完毕\n");return -1;}}
}

tftp.h

#ifndef TFTP_H
#define TFTP_H
#define SER_PORT 69
#define SER_IP "192.168.1.4"
#define N 516
#include<myhead.h>
//菜单
void menu();//上传
int upload(int cfd , char *filename);//下载
int download(int cfd ,char *filename);#endif

效果展示

 

http://www.lryc.cn/news/429373.html

相关文章:

  • Vue 3 + Pinia 实现网页刷新功能
  • DVWA综合靶场漏洞讲解
  • 实现Bezier样条曲线
  • MySQL中的EXPLAIN的详解
  • LearnOpenGL——SSAO学习笔记
  • [C语言]-基础知识点梳理-文件管理
  • pcdn闲置带宽被动收入必看教程。第五讲:光猫更换和基础设置
  • 工业数据采集网关简介-天拓四方
  • Java 调整字符串,验证码生成
  • 【专题】全球商用服务机器人市场研究(2023)报告合集PDF分享(附原数据表)
  • SQL UA注入 (injection 第十八关)
  • 初阶数据结构之计数排序
  • 【开端】记一次诡异的接口排查过程
  • jenkins最佳实践(二):Pipeline流水线部署springCloud微服务项目
  • 第2章 C语言基础知识
  • 鹭鹰优化算法SBOA优化RBF神经网络的扩散速度实现多数入多输出数据预测,可以更改数据集(MATLAB代码)
  • MySQL基础练习题48-连续出现的数字
  • webrtc学习笔记2
  • Simple RPC - 06 从零开始设计一个服务端(上)_注册中心的实现
  • 【深度学习】基于Transformers的大模型推理框架
  • 电脑监控怎样看回放视频?一键解锁电脑监控回放,守护安全不留死角!高效员工电脑监控,回放视频随时查!
  • 【一起学Rust | 框架篇 | Tauri2.0框架】tauri中rust和前端的相互调用(rust调用前端)
  • deque容器
  • Redis远程字典服务器(9)—— 类型补充
  • VMware虚拟机nat无法联通主机
  • 「字符串」详解AC自动机并实现对应的功能 / 手撕数据结构(C++)
  • freecad遭遇网络不同无法安装插件Addon Manager: Unexpected 0 response from server
  • Ruby模板引擎:构建动态视图的艺术
  • HarmonyOS NEXT星河版零基础入门(3)
  • 第二十讲 python中的异常结构-try except-else-finally