基于UDP的TFTP文件传输-实现网盘上传下载功能

news2024/10/5 15:33:56

数据传输模式:octet(二进制模式)

#include<head.h>
char* down_up_request(char* buf,char* filename,int rw,int sockfd,struct sockaddr_in in);
int download(struct sockaddr_in in,char* filename,char* buf,int sockfd);
int upload(struct sockaddr_in in,char* filename,char* buf,int sockfd);
int main(int argc, const char *argv[])
{
	/***********************************
	基于UDF的TFTP文件传输,实现网盘功能
	***********************************/
	/**********客户端代码**************/
	//创建套接文件
	int rtsocket=socket(AF_INET,SOCK_DGRAM,0);
	if(rtsocket==-1){
		perror("socket");
		return -1;
	}
	else{
		printf("套接文件创建成功\n");
	}
	//绑定客户端端口与IP
	struct sockaddr_in cin;
	char* cip="192.168.176.130";
	uint16_t cport=8888;
	cin.sin_family=AF_INET;
	cin.sin_port=htons(cport);
	cin.sin_addr.s_addr=inet_addr(cip);
	int rtbind=bind(rtsocket,(struct sockaddr*)&cin,sizeof(cin));
	if(rtbind==0){
		printf("与客户端绑定成功\n");
	}
	else if(rtbind==-1){
		perror("bind");
		return -1;
	}
	//数据收发
	/*填充服务器地址与端口信息*/
	struct sockaddr_in sin;
	char* sip="192.168.118.161";
	uint16_t sport=69;
	sin.sin_family=AF_INET;
	sin.sin_port=htons(sport);
	sin.sin_addr.s_addr=inet_addr(sip);
	/*********************************/
	char data[516]={0};
	char filename[128]={0};
	printf("*******1<download>*******\n");
	printf("*******2<upload>*********\n");
	printf("*******3<exit>***********\n");
	while(1){
		int option=0;
		printf("please choose option:");
		scanf("%d",&option);
	if(option<1&&option>3){
		printf("enter error,please reenter\n");
		scanf("%d",&option);
	}
		switch(option){
		case 1 :
			{
				printf("please enter download filename:");
				scanf("%s",filename);
				getchar();
				char* rt=down_up_request(data,filename,1,rtsocket,sin);
				download(sin,filename,rt,rtsocket);
			}
			break;
		case 2:
			{
				printf("please enter upload filename:");
				scanf("%s",filename);
				getchar();
				char* rt=down_up_request(data,filename,2,rtsocket,sin);
				upload(sin,filename,rt,rtsocket);
			}
			break;
		case 3: 
			{
				goto END;

			}
			break;
		}
	}
END:
	close(rtsocket);
	return 0;
}
//下载或上传请求
char* down_up_request(char* buf,char* filename,int rw,int sockfd,struct sockaddr_in in){
	short* p1=(short*)buf;
	*p1=htons(rw);//rw操作码转为网络字节序
	char* p2=buf+2;
	strcpy(p2,filename);//存入要下载的文件名
	char* p3=p2+strlen(p2)+1;
	strcpy(p3,"octet");//设置操作模式
	int size=2+sizeof(p2)+1+sizeof(p3)+1;
	ssize_t rtsendto=sendto(sockfd,buf,size,0,(struct sockaddr*)&in,sizeof(in));
	if(rtsendto==-1){
		perror("sendto");
		return NULL;
	}
	else{
		printf("发送请求成功\n");
	}
	return buf;
}
//下载
int download(struct sockaddr_in in,char* filename,char* buf,int sockfd){
	int fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC,0666);
	if(fd==-1){
		perror("open");
		return -1;
	}
		short num=0;
		socklen_t addrlen=sizeof(in);
		while(1){
		bzero(buf,sizeof(buf));
		ssize_t rtrecvfrom=recvfrom(sockfd,buf,516,0,(struct sockaddr*)&in,&addrlen);//循环接收数据
		if(rtrecvfrom==-1){
			perror("recvfrom");
			return -1;
		}
		else{
			printf("reading......\n");
		}
		if(buf[1]==3){//判断是否是数据包
			if(*(short*)(buf+2)==htons(num+1)){//确认块编号接发是否一致
				num++;
				if(rtrecvfrom-4==512){//数据包后512字节为数据
					ssize_t rtwrite=write(fd,buf+4,rtrecvfrom-4);
					if(rtwrite<0){
						printf("write error\n");
						break;
					}
				}
				char ACK[4]={0};
				short *p=(short*)ACK;
				*p=htons(4);
				short *p1=(short*)(ACK+2);
				*p1=htons(num);
				ssize_t rtsendto=sendto(sockfd,ACK,4,0,(struct sockaddr*)&in,addrlen);//写入成功,向服务器发送ACK,确认
				if(rtsendto==-1){
					perror("sendto");
					return -1;
				}
				if(rtrecvfrom<516){//读取小于516说明已经读取结束
					ssize_t rtwrite=write(fd,buf+4,rtrecvfrom-4);
					if(rtwrite<0){
						printf("write error\n");
						break;
					}
					printf("end of download\n"); 
					close(fd);  
					break;
				}
			}
		} 
		else if(buf[1]==5){ //错误信息
			printf("error:%s\n",buf+4);
			close(fd);
			return -1;
		}
	}
}
//上传
int upload(struct sockaddr_in in,char* filename,char* buf,int sockfd){
    int fd=open(filename,O_RDONLY);
    if(fd==-1){
        printf("file don't exist\n");
        return -1;
    }
        short num=0;
        socklen_t addrlen=sizeof(in);
        while(1){
        bzero(buf,sizeof(buf));
        ssize_t rtrecvfrom=recvfrom(sockfd,buf,4,0,(struct sockaddr*)&in,&addrlen);//循环接收服务器确认消息
        if(rtrecvfrom==-1){
            perror("recvfrom");
            return -1;
        }
        else{
            printf("ready upload....\n");
        }
	//	printf("ACK=%d\n",ntohs(*(short*)(buf+2)));//查看第一次发过来的ack
	//	解析服务器数据,读取并发送数据包给服务器
        if(buf[1]==4){//判断服务器是否发来ACK
            if(*(short*)(buf+2)==htons(num)){//确认块编号接发是否一致,从0开始
                ssize_t rtread=read(fd,buf+4,512);
				printf("uploading.......\n");
			//	printf("rtread=%ld\n",rtread);
                short *p=(short*)buf;
                *p=htons(3);//修改为数据包,服务器识别数据包下载数据
				num++;//ACK块编码确认+1给服务器确认
                short *p1=(short*)(buf+2);
                *p1=htons(num);
                ssize_t rtsendto=sendto(sockfd,buf,rtread+4,0,(struct sockaddr*)&in,addrlen);//将上传的文件以每512字节发送给服务器,并发送ACK确认
                if(rtsendto==-1){
                    perror("sendto");
                    return -1;
                }
                if(rtread<512){//读取小于512说明上传的文件已经读取完毕
                    printf("upload success\n");
                    close(fd);
                    break;
                }
            }
        }
        else if(buf[1]==5){ //错误信息
            printf("error:%s\n",buf+4);
            close(fd);
            return -1;
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1700593.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【深度学习】多层感知器MLP模型对 MNIST 数据集中的手写数字进行分类

本模型是解决一个十分类的问题&#xff1a; 在这之前&#xff0c;可以先看看一个Pytorch的简单的示例&#xff1a; 它展示了如何定义一个简单的神经网络、准备数据、训练模型以及评估模型&#xff1a; import torch import torch.nn as nn import torch.optim as optim …

私有云和多云管理平台 | Cloudpods v3.10.15 正式发布

功能优化 【主机】裸金属详情页增加部分属性信息【监控】优化告警策略&#xff0c;支持同时设置多监控指标【主机】支持透传设备自动探测【主机】LVM 块存储支持快照【监控】简化 Telegraf 容器的挂载点【主机】新建 VMware 支持同时填写备注信息【存储】KVM 支持对接 LVM 存储…

融汇11款AI工具构建完美应用

本文将为您介绍25个开源项目&#xff0c;分为上下两篇以便您融汇它们来制作自己的AI应用。人工智能&#xff08;AI&#xff09;应用在近年来得到了长足的发展。从语音助手到软件开发&#xff0c;人工智能已在我们的生活中无处不在&#xff0c;并得到了广泛应用。 如您所见&…

深入解析内置模块OS:让你的Python代码更懂操作系统

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、OS模块简介与基础应用 二、文件与目录操作详解 三、OS模块的高级应用&#xff1a;双色…

【NumPy】关于numpy.mean()函数,看这一篇文章就够了

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

【竞技宝】西甲:锋霸想和尤文再续前缘,三进宫能否实现?

马竞本赛季的比赛任务已经全部完成,整体来说床单军团的发挥无法让球迷们满意,休赛期球队肯定会有很多补强和调整。根据西班牙媒体报道,球队锋线大将莫拉塔不满自己在球队的出场时间,希望今年夏天离开球队。而西班牙锋霸想要去的球队也已经浮出水面,那就是他曾经效力过的尤文图斯…

【字典树(前缀树) 字符串】2416. 字符串的前缀分数和

本文涉及知识点 字典树&#xff08;前缀树) 字符串 LeetCode 2416. 字符串的前缀分数和 给你一个长度为 n 的数组 words &#xff0c;该数组由 非空 字符串组成。 定义字符串 word 的 分数 等于以 word 作为 前缀 的 words[i] 的数目。 例如&#xff0c;如果 words [“a”,…

【NOIP2015普及组复赛】题3:求和

题3&#xff1a;求和 【题目描述】 一条狭长的纸带被均匀划分出了 n n n 个格子&#xff0c;格子编号从 1 1 1 到 n n n。每个格子上都染了一种颜色 c o l o r i color_i colori​ &#xff08;用 [ 1 &#xff0c; m ] [1&#xff0c;m] [1&#xff0c;m]当中的一个整数表…

【数据结构】排序算法大全(快速、堆、归并、插入、折半、希尔、冒泡、计数、基数)各算法比较、解析+完整代码

文章目录 八、排序1.插入排序1.1 直接插入排序1.2 折半插入排序1.3 希尔排序 2.交换排序2.1 冒泡排序2.2 快速排序 3.选择排序3.1 简单选择排序3.2 堆3.2.1 堆排序3.2.2 堆插入删除*完善代码 堆 4.归并、基数、计数排序4.1 归并排序4.2 基数排序4.3 计数排序 5.内部排序算法的比…

JAVA:Spring Boot整合MyBatis Plus持久层

1、简述 MyBatis Plus是MyBatis的增强工具包&#xff0c;它在MyBatis的基础上进行了扩展&#xff0c;提供了许多便捷的功能&#xff0c;例如通用CRUD操作、分页插件、代码生成器等。使用MyBatis Plus&#xff0c;开发者可以更加方便地进行持久层操作&#xff0c;并且减少了很多…

Python爬虫实战:利用代理IP获取电商数据

文章目录 1.电商数据介绍2.爬取目标3.代理IP推荐4.准备工作4.1 模块安装4.2 代理IP获取 5.爬虫代码实战5.1分析网页5.1.1 获取cookie5.1.2 关键词分析5.1.3 翻页分析5.1.4 数据获取分析 5.2 发送请求5.3 提取数据5.4 保存数据5.5 完整源码5.6 数据分析六、总结 1.电商数据介绍 …

[随笔] 在CSDN的6周年纪念日随笔

纪念 转眼已过6年&#xff0c;大一的时候学习编程&#xff0c;潜水 CSDN 学习各类博文&#xff0c;才学浅薄就没有主动写博文记录自己的学习历程。 过了段时间刚刚到了大二&#xff0c;很喜欢 Todolist&#xff0c;意气风发的写下《一份清爽的编程计划》&#xff0c;哈哈。 …

冷冻式压缩空气干燥机常见几种系统原理图

冷冻式压缩空气干燥机 我们以两种典型的设计流程图为例 1.干式蒸发型&#xff0c;这类冷干机是我们最为常见的设计型式。下图为deltech公司的典型流程图 此类设备各家设计不同的最大区别基本就是在换热器的结构型式上有比较大的区别。换热器主要有&#xff1a;管壳式、铝板换、…

【openlayers系统学习】00官网的Workshop介绍

00Workshop介绍 官方文档&#xff1a;https://openlayers.org/workshop/en/ openlayers官网Workshop学习。 通过官网Workshop&#xff0c;系统学习openlayers的使用。 基本设置 这些说明假定您从最新Workshop版本的 openlayers-workshop-en.zip​ 文件开始。此外&#xff…

KingbaseES数据库merge语法

数据库版本&#xff1a;KingbaseES V008R006C008B0014 简介 MERGE 语句是一种用于数据操作的 SQL 语句&#xff0c;它能够根据指定的条件将 INSERT、UPDATE 和 DELETE 操作结合到单个语句中。其主要作用是在目标表和源表之间进行数据比较和同步&#xff0c;根据条件的匹配情况来…

IBERT眼图扫描(高速收发器八)

前文讲解了GTX的时钟及收发数据通道的组成&#xff0c;之后讲解了眼图、加重、均衡等原理及原因&#xff0c;本文通过xilinx提供的IBERT IP完成实际工程的眼图扫描&#xff0c;确定加重和幅值调节的参数。 1、回环模式 在此之前&#xff0c;需要了解一下GTX的回环模式。如果板…

批处理作业调度问题 (回溯法)

目录 一、问题解析 二、实例剖析 三、算法思路 四、代码实现 结果&#xff1a; 总结 前言 【问题】n 个作业{1, 2, …, n}要在两台机器上处理&#xff0c;每个作业必须先由机器 1 处理&#xff0c;再由机器 2 处理&#xff0c;机器 1 处理作业i所需时间为 ai&#xff0c;…

【Unity实战篇 】| Unity实现 文本框可以自适应大小,到达最大宽度之后再缩小字体

前言 在文本框可以自适应大小拉伸的前提下,增加一个最大限制宽度,使其到达最大宽度后 再启用 Best Fit 实现自适应改变文字大小以适应文本框的大小。 【Unity实战篇 】 | Unity实现 Text文本框可以自适应大小,到达最大宽度之后再缩小字体 在Unity中经常会用到文本组件的自…

Jmeter插件下载(下载和使用教程)

插件管理器&#xff1a;plugins-manager下载安装和使用 下载&#xff1a; 官网地址&#xff1a;https://jmeter-plugins.org/install/Install/ 步骤1&#xff1a;将下载jmeter-plugins-manager-1.10.jar放到目录apache-jmeter-5.1.1\lib\ext&#xff0c;如下图 步骤2&#x…

《最新出炉》系列入门篇-Python+Playwright自动化测试-42-强大的可视化追踪利器Trace Viewer

宏哥微信粉丝群&#xff1a;https://bbs.csdn.net/topics/618423372 有兴趣的可以扫码加入 1.简介 在我们日常执行自动化测试工作的过程中&#xff0c;经常会遇到一些偶发性的bug&#xff0c;但是因为bug是偶发性的&#xff0c;我们不一定每次执行都能复现&#xff0c;所以我…