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

数据传输模式: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;
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据结构(七)查找

2024年5月26日一稿(王道P291) 7.1 查找的基本概念 7.2 顺序查找和折半查找 7.2.1 顺序查找 7.2.2 折半查找 7.2.3 分块查找 7.3 树形查找 7.3.1 二叉排序树(BST)

FFmpeg+QT播放器实战1---UI页面的设计

1、播放器整体布局的设计 该部分使用QT的UI工具&#xff0c;进行整体页面设置&#xff0c;如下图1所示&#xff1a; 2、控制布局的设计 创建ctrBar的UI页面并进行页面布局设置&#xff0c;如下图2所示&#xff1a; 将图1中ctrBarWind对象提升为ctrBar类(该界面替代原先的控…

Modbus TCP转Profinet网关测试配置案例

本案例采用XD-ETHPN20网关做为Modbus TCP通信协议设备与Profinet通信协议设备连接的桥梁。Modbus TCP是一种基于TCP/IP协议的工业通信协议&#xff0c;而Profinet则是用于太网通信的协议。Modbus TCP转Profinet网关可实现这两种不同协议之间的数据交换和传输&#xff0c;极大地…

实在智能TARS:面向垂直领域自主训练的类GPT大模型

一、写在前面 在数字化浪潮的推动下&#xff0c;企业正寻求突破传统生产力的局限&#xff0c;以实现更高效、更智能的运营模式。实在智能科技有限公司的TARS产品&#xff0c;以其前沿的人工智能技术&#xff0c;为企业注入了新质生产力&#xff0c;引领着智能化转型的新潮流。…

数据结构(三)循环链表

文章目录 一、循环链表&#xff08;一&#xff09;概念&#xff08;二&#xff09;示意图&#xff08;三&#xff09;操作1. 创建循环链表&#xff08;1&#xff09;函数声明&#xff08;2&#xff09;注意点&#xff08;3&#xff09;代码实现 2. 插入&#xff08;头插&#x…

专业渗透测试 Phpsploit-Framework(PSF)框架软件小白入门教程(十二)

本系列课程&#xff0c;将重点讲解Phpsploit-Framework框架软件的基础使用&#xff01; 本文章仅提供学习&#xff0c;切勿将其用于不法手段&#xff01; 接上一篇文章内容&#xff0c;讲述如何进行Phpsploit-Framework软件的基础使用和二次开发。 我们&#xff0c;继续讲一…

【Django项目】 音乐网站spotify复刻

代码&#xff1a;https://github.com/tomitokko/spotify-clone 注&#xff1a;该项目不是自己提供mp3文件&#xff0c;而是使用spotify 的api接口获取。

用实践结果告诉你为啥说 CloudFlare 是赛博菩萨?

最近几天明月都没有更新博客了,主要是接了几个 CloudFlare 代维配置的活儿,有需要加速优化的,有需要排除疑难故障的,有需要提高防御攻击能力的甚至还有纯粹为了体验“打不死”装逼需要的。总之,各种各样的需求,五花八门的,好在 CloudFlare 都能一一满足,最主要的是这些…

C++入门:从C语言到C++的过渡(3)

目录 1.内联函数 1.1内联函数的定义 1.2特性 2.auto关键字 2.1auto的简介 2.2注意事项 3.范围for 4.nullptr空指针 1.内联函数 在C语言中&#xff0c;无论使用宏常量还是宏函数都容易出错&#xff0c;而且无法调试。而C为了弥补这一缺陷&#xff0c;引入了内联函数的概…

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

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

前端手写文件上传;使用input实现文件拖动上传

使用input实现文件拖动上传 vue2代码&#xff1a; <template><div><div class"drop-area" dragenter"highlight" dragover"highlight" dragleave"unhighlight" drop"handleDrop"click"handleClick&quo…

嵌入式C语言中结构体使用详解

各位开发者大家好,今天给大家分享一下,嵌入式C语言中结构体的使用方法。 第一个:内存对齐 内存对齐是指一个数据类型在内存中存放时,对其地址的要求。简单来说内存对齐就是使得其内存地址是该类型大小的整数倍,例如 double 类型的变量,其内存地址需要是8的倍数(double大…

数据结构(四)

数据结构&#xff08;四&#xff09; 算法算法的特征算法和程序的区别怎么样评判一个算法的好坏 常见的查找算法线性树状哈希查找构建哈希函数的方法质数求余法解决冲突 算法 一堆指令的有序集合 算法的特征 唯一性&#xff1a;每一句话只有一种解释 有穷性&#xff1a;算法能…

澳大利亚.德国-门户媒体投放通稿:需要注意什么地方

概述 在现代社会&#xff0c;新闻媒体的投放成为企业和组织宣传推广的重要手段之一。澳大利亚和德国作为全球重要的经济和科技中心&#xff0c;其新闻媒体也备受关注。本文将介绍澳大利亚和德国的一些主要新闻媒体&#xff0c;并讨论发表新闻稿时需要注意的地方。 澳大利亚媒…

Python小游戏——俄罗斯方块

文章目录 项目介绍环境配置代码设计思路1.初始化和导入库&#xff1a;2.定义颜色和屏幕尺寸&#xff1a;3.定义游戏逻辑&#xff1a;4.游戏循环&#xff1a; 源代码效果图 项目介绍 俄罗斯方块游戏是一款经典的益智游戏&#xff0c;玩家通过旋转和移动各种形状的方块&#xff…

VolWeb:集中式增强型数字取证内存分析平台

关于VolWeb VolWeb是一款最新开发的集中式增强型数字取证内存分析平台&#xff0c;该平台基于Volatility 3框架实现其功能&#xff0c;该工具旨在辅助广大研究人员执行安全分析和事件应急响应等任务。 VolWeb可以提供集中式、可视化的增强型网络应用程序&#xff0c;并提高安全…

如何在 Elasticsearch 中选择精确 kNN 搜索和近似 kNN 搜索

作者&#xff1a;来自 Elastic Carlos Delgado kNN 是什么&#xff1f; 语义搜索&#xff08;semantic search&#xff09;是相关性排名的强大工具。 它使你不仅可以使用关键字&#xff0c;还可以考虑文档和查询的实际含义。 语义搜索基于向量搜索&#xff08;vector search&…

flink cdc mysql整理与总结

文章目录 一、业务中常见的需要数据同步的场景CDC是什么FlinkCDC是什么CDC原理为什么是FlinkCDC业务场景flink cdc对应flink的版本 二、模拟案例1.阿里云flink sql2.开源flink sql(单机模式)flink 安装安装mysql3.flink datastream 三、总结 提示&#xff1a;以下是本篇文章正文…

行业分析---造车新势力之蔚来汽车

1 前言 在之前的博客中&#xff0c;笔者分析了苹果《行业分析---我眼中的Apple Inc.》&#xff0c;苹果已经成为世界级的公司。随后也分析了电动汽车公司特斯拉《行业分析---马斯克的Tesla》&#xff0c;特斯拉也在不断成长。目前能分析的新能源汽车公司不多&#xff0c;小米汽…

C#对文件进行批量重命名或者对某个单独的文件进行改名

目录 一、FolderBrowserDialog 二、OpenFileDialog 三、Path 四、ui设计 五、代码部分 一、FolderBrowserDialog FolderBrowserDialog是一个用于选择文件夹的对话框控件&#xff0c;可以在windows Forms应用程序中使用。使用它可以让用户选择一个文件夹&#xff0c;并返…