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

基于UDP的TFTP文件传输

代码:

#include <myhead.h>//实现下载功能
int download(int cfd,struct sockaddr_in sin)
{char buf[516] = "";  //定义资源包char fileName[128] = "";  //定义文件名printf("请输入文件名:");scanf("%s",fileName);  getchar();//打开文件int fd = -1;if((fd = open(fileName,O_RDWR|O_CREAT|O_TRUNC|0666)) == -1){perror("open error");  //读写形式创建文件,文件名为输入的文件名return -1;}//组装请求包short *p1 = (short *)buf;*p1 = htons(1);char *p2 = buf + 2;strcpy(p2,fileName);char *p3 = p2+strlen(p2)+1;strcpy(p3,"octet"); int size = 4+strlen(p2)+strlen(p3);  //整体长度//先发送下载请求到服务器if(sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin))==-1){perror("sendto error");return -1;}printf("请求成功!\n");socklen_t socklen = sizeof(sin);char *p5 = buf + 4; //确定数据的位置以及差错信息的位置while(1){bzero(buf,sizeof(buf));int res=recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&socklen);int A = buf[1];  //因为小端存储,操作码放在buf的第二位if(A == 3)  //当操作码为3时,证明是数据包,正常接收{write(fd,p5,sizeof(buf));buf[1]=4;   //将操作码改为4,即ACK//将buf前四位发送回去,因为操作码已经修改,发回去四位当做ACK回复sendto(cfd,buf,4,0,(struct sockaddr*)&sin,sizeof(sin));}else if(A == 5)  //当操作码为5时,证明为ERROR{printf("%s\n",p5);return -1;}if(res < 516)  //当接收到的字节数小于516时,证明已经接收完成,关闭循环break;}printf("下载完成\n");close(fd);  //关闭文件
}//实现上传功能
int upload(int cfd,struct sockaddr_in sin)
{char buf[516] = "";  //定义资源包char fileName[128] = "";  //定义文件名printf("请输入文件名:");scanf("%s",fileName);  getchar();//打开文件int fd = -1;if((fd = open(fileName,O_RDONLY)) == -1){perror("open error");  //只读形式打开文件,文件名为输入的文件名return -1;}//组装请求包short *p1 = (short *)buf;*p1 = htons(2);   //操作码为2代表要上传char *p2 = buf + 2;strcpy(p2,fileName);char *p3 = p2+strlen(p2)+1;strcpy(p3,"octet"); int size = 4+strlen(p2)+strlen(p3);  //整体长度//先发送上传请求到服务器if(sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin))==-1){perror("sendto error");return -1;}printf("请求成功!\n");socklen_t socklen = sizeof(sin);int n = 1;while(1){bzero(buf,sizeof(buf));recvfrom(cfd,buf,4,0,(struct sockaddr*)&sin,&socklen);int res = read(fd,buf+4,sizeof(buf)-4); //将文件的512位写入数据包buf[1]=3;   //将操作码改为3,即数据包//将buf发送,因为操作码已经修改,发回去数据加上了操作码和块编号sendto(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin));if(res==0)  //证明已经上传完成,关闭循环break;}printf("上传完成\n");close(fd);  //关闭文件}
int main(int argc, const char *argv[])
{if(argc != 2){printf("input error");return -1;}//创建套接字int cfd = socket(AF_INET,SOCK_DGRAM,0);if(cfd == -1){perror("socket error");return -1;}//填充服务器结构体struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(69);sin.sin_addr.s_addr = inet_addr(argv[1]);int key = 0;while(1){system("clear");printf("\t\t菜单\t\t\n");printf("\t\t1.下载\t\t\n");printf("\t\t2.上传\t\t\n");printf("\t\t0.关闭\t\t\n");printf("请输入选项:");scanf("%d",&key);getchar();switch(key){case 1:{//下载int A =download(cfd,sin);};break;case 2:{//上传int B =upload(cfd,sin);};break;case 0:{goto A;};break;default:printf("请输入正确的选项!\n");}//阻塞printf("输入任意键,按回车清空");while(getchar() != '\n');}A:close(cfd);return 0;
}

上传文件
在这里插入图片描述
下载文件
在这里插入图片描述

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

相关文章:

  • 抵御代码重用攻击:指针认证(PAC)和分支目标识别(BTI)
  • 业务逻辑漏洞
  • Vue框架学习笔记——计算属性
  • 初识PO模式并在Selenium中简单实践
  • 读书笔记:彼得·德鲁克《认识管理》第35章 以任务和工作为中心的设计
  • 算法基础课 (一) 基础算法
  • 【Python】jieba分词基础
  • 使用jmeter对接口进行简单测试
  • 成长在于积累——https 认证失败的学习与思考
  • C语言——数字金字塔
  • 关于 typedef 的用法
  • Webshell流量分析
  • 高级IO—poll,epoll,reactor
  • 一文详解Python中常用数据类型
  • 【MATLAB源码-第85期】基于farrow结构的滤波器仿真,截止频率等参数可调。
  • ChatGPT Plus/GPT4高级数据分析和插件功能详解
  • 【Android Jetpack】Room数据库
  • 自定义中间件
  • 优化机器学习:解析数据归一化的重要性与应用
  • 五分钟,Docker安装flink,并使用flinksql消费kafka数据
  • 【小聆送书第一期】让架构师的成神之路温暖你这个不景气的冬天
  • 网页爬虫反扒措施有哪些?
  • C#实现批量生成二维码
  • 3种在ArcGIS Pro中制作山体阴影的方法
  • 【ChatGLM2-6B】Docker下部署及微调
  • 输入两个整数,输出它们的乘积。 ← Python 及 C++ 代码比较
  • C语言——从键盘输人一个表示年份的整数,判断该年份是否为闰年,并显示判断结果。
  • 出于隐私和安全的考虑,有时需要从谷歌删除你的个人数据,有两种方法
  • 【同一局域网下】两台电脑之间互ping
  • 【精选】Ajax技术知识点合集