网络编程(TFTP协议实验)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#define PORT 69       //端口号:填服务器绑定端口号
#define IP   "192.168.1.101"   //IP地址:windows的IP地址

int upload(int cfd,struct sockaddr_in sin)
{
	char filename[20] = "";
	printf("请输入要上传的文件名>>> ");
	scanf("%s", filename);
	while(getchar()!=10);

	//判断文件存不存在
	int fd = open(filename,O_RDONLY);
	if(fd < 0)
	{
		ERR_MSG("open");
		return -1;
	}
	//发送数据
	char buf[516] = "";
	int size = sprintf(buf, "%c%c%s%c%s%c", 0, 2, filename, 0, "octet", 0);
	if(sendto(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin)) < 0) 
	{
		ERR_MSG("sendto");
		return -1;
	}
	printf("sendto success\n");
	socklen_t addrlen = sizeof(sin);
	ssize_t res = 0;
	unsigned short num = 0;      //本地记录的块编号

	while(1)
	{
		bzero(buf, sizeof(buf));
		//接收服务器的应答
		res = recvfrom(cfd, buf, sizeof(buf), 0, (struct sockaddr*)&sin, &addrlen);
		if(res < 0)
		{
			ERR_MSG("recvfrom");
			break;
		}

		if(4 == buf[1])
		{
			if(htons(num) == *(unsigned short*)(buf+2))
			{
				//组数据包给服务器
				num++;
				*(unsigned short*)buf = htons(3);
				*(unsigned short*)(buf+2) = htons(num);

				res = read(fd, buf+4, 512);
				if(res < 0)
				{
					break;
				}
				else if(0 == res)
				{
					printf("文件:%s 上传完毕\n", filename);
					break;
				}

				//发送数据包
				if(sendto(cfd, buf, res+4, 0, (struct sockaddr*)&sin, sizeof(sin)) < 0)
				{
					ERR_MSG("sendto");
					return -1;
				}
			}
		}
		else if(5 == buf[1])//错误包
		{
			printf("MSG_ERR: code[%d] msg[%s] __%d__\n", \
					ntohs(*(unsigned short*)(buf+2)), buf+4, __LINE__);
			break;
		}

	}

	close(fd);
	return 0;
}

int download(int cfd,struct sockaddr_in sin)
{

	char buf[516] = "";

	char filename[20] = "";
	printf("请输入要下载的文件名>>> ");
	scanf("%s", filename);
	while(getchar()!=10);

	//发送下载请求
	//组协议包
	int size = sprintf(buf, "%c%c%s%c%s%c", 0, 1, filename, 0, "octet", 0);
	//sendto 
	if(sendto(cfd, buf, size, 0, (struct sockaddr*)&sin, sizeof(sin)) < 0)
	{
		ERR_MSG("sendto");
		return -1;
	}

	//本地创建并打开要下载的文件
	int fd = -1;     //必须初始化一个无意义的文件描述符,否则下面的close

	socklen_t addrlen = sizeof(sin);
	ssize_t res = 0;
	unsigned short num = 0;      //本地记录的块编号

	//循环接收数据包,回复ACk
	while(1)
	{
		bzero(buf, sizeof(buf));
		//接收数据包
		res = recvfrom(cfd, buf, sizeof(buf), 0, (struct sockaddr*)&sin, &addrlen);
		if(res < 0)
		{
			ERR_MSG("recvfrom");
			break;
		}

		if(3 == buf[1])     //数据包
		{
			if(htons(num+1) == *(unsigned short*)(buf+2))
			{
				num++;

				if(-1 == fd)
				{
					fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0664);
					if(fd < 0)
					{
						ERR_MSG("open");
						break;
					}
				}

				//将获取到的数据,写入到文件中
				if(write(fd, buf+4, res-4) < 0)
				{
					ERR_MSG("write");
					break;
				}

				buf[1] = 4;
				if(sendto(cfd, buf, 4, 0, (struct sockaddr*)&sin, sizeof(sin)) < 0)
				{
					ERR_MSG("sendto");
					break;
				}

				if(res-4 < 512)
				{
					printf("======= 文件下载完毕 =======\n");
					break;
				}
			}
		}
		else if(5 == buf[1])//错误包
		{
			printf("MSG_ERR: code[%d] msg[%s] __%d__\n", \
					ntohs(*(unsigned short*)(buf+2)), buf+4, __LINE__);
			break;
		}

	}
	close(fd);
	return 0;
}
int main(int argc, const char *argv[])
{
	//创建报式套接字
	int cfd = socket(AF_INET,SOCK_DGRAM,0);
	if(cfd < 0)
	{
		ERR_MSG("socket");
		return -1;
	}
	printf("cfd = %d\n",cfd);

	//绑定客户端的地址信息结构体到套接字上--->非必须绑定
	//若不绑定,则操作系统会给客户端绑定上客户端所在的主机IP以及随机端口(49151~65535)

	//填充地址信息结构体,真实的地址信息结构体根据地址族制定
	//AF_INET:man 7 ip
	//要连接哪个服务器,就填对应服务器的IP和端口
	struct sockaddr_in sin;
	sin.sin_family      = AF_INET;       //必须填AF_INET
	sin.sin_port        = htons(PORT);   //端口号:填服务器绑定端口号
	sin.sin_addr.s_addr = inet_addr(IP);  //IP地址:服务器绑定的IP地址

	char c = 0;

	while(1)
	{	
		printf("-------------------------\n");
		printf("---------1.下载----------\n");
		printf("---------2.上传----------\n");
		printf("-------------------------\n");
		printf("请输入>>> ");
		c = getchar();
		while(getchar()!=10);
		switch(c)
		{
		case '1' :
			download(cfd,sin);
			break;
		case '2' :
			upload(cfd,sin);
			break;
		default :
			printf("输入错误,请重新输入\n");
			break;
		}
		while(getchar()!=10);

	}

	//关闭所有文件描述符
	close(cfd);

	return 0;
}

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

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

相关文章

16通道AD采集FMC子卡推荐哪些?

FMC149是一款16通道65MHz采样率14位直流耦合AD采集FMC子卡&#xff0c;符合VITA57.1规范&#xff0c;可以作为一个理想的IO模块耦合至FPGA前端&#xff0c;16通道AD通过FMC连接器&#xff08;HPC&#xff09;连接至FPGA从而大大降低了系统信号延迟。 该板卡支持板上可编程采样…

难解的bug

android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord 【Android TimeCat】 解决 context.startforegroundservice() did not then call service.startforeground() | XiChens Blog http://www…

Vue+ElementUI实现选择指定行导出Excel

这里记录一下&#xff0c;今天写项目时 的一个需求&#xff0c;就是通过复选框选中指定行然后导出表格中选中行的Excel表格 然后这里介绍一个工具箱(模板)&#xff1a;vue-element-admin 将它拉取后&#xff0c;运行就可以看到如下界面&#xff1a; 这里面的很多功能都已经实现…

【TypeScript】进阶之路语法细节,类型和函数

进阶之路 类型别名(type)的使用接口(interface)的声明的使用二者区别&#xff1a; 联合类型和交叉类型联合类型交叉类型 类型断言获取DOM元素 非空类型断言字面量类型的使用类型缩小&#xff08;类型收窄&#xff09;TypeScript 函数类型函数类型表达式内部规则检测函数的调用签…

线性规划模型-应用篇

文章目录 模型特点使用技巧工具包和求解器模型线性化 应用实例经验总结 模型特点 上一篇中&#xff0c;详细阐述了线性规划问题和单纯形法的算法原理&#xff0c;本文将着重介绍线性模型在工业场景中的应用。 首先需要说清楚的是&#xff0c;为什么线性模型深受研发人员青睐。…

【dnf5文档】新一代RedHat自动化包管理器

前言 HI,CSDN的码友们&#xff0c;距离上一次我发文章已经过去了半年的时间&#xff0c;现在我又来介绍自己新发现和探究的开源技术了。计算机的发展总是飞速的&#xff0c;当我在写这篇文章的时候&#xff0c;Fedora rawhide已经进入了40版本、默认采用的自动化包管理器为dnf…

iPhone苹果手机触屏失灵无法关机,如何强制重启

参考:https://zhuanlan.zhihu.com/p/615223121 1&#xff0c;只轻按一下音量上键后快速松开 2&#xff0c;只轻按一下音量下键后快速松开 3&#xff0c;只按住右侧电源键长按不松手&#xff0c;直到手机关机。

什么是CSS中的渐变(gradient)?如何使用CSS创建线性渐变和径向渐变?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 渐变&#xff08;Gradient&#xff09;在CSS中的应用⭐ 线性渐变&#xff08;Linear Gradient&#xff09;语法&#xff1a;示例&#xff1a; ⭐ 径向渐变&#xff08;Radial Gradient&#xff09;语法&#xff1a;示例&#xff1a; ⭐ 写…

CentOS安装Postgresql

PG基本安装步骤 安装postgresql&#xff1a; sudo yum install postgresql-server初始化数据库&#xff1a;安装完毕后&#xff0c;需要初始化数据库并创建初始用户&#xff1a; sudo postgresql-setup initdb启动和停止服务&#xff1a; sudo systemctl start postgresql sudo…

FreeRTOS源码分析-12 低功耗管理

目录 1 STM32低功耗管理概念及应用 1.1睡眠模式 1.2 停止模式 1.3 待机模式 2 Tickless低功耗管理 2.1 Tickless低功耗模式介绍 2.2 FreeRTOS低功耗模式配置 2.3 FreeRTOS低功耗模式应用 3 低功耗管理实际项目开发 3.1 低功耗设计必须要掌握的硬件知识 …

什么是BFC?它有什么作用?如何创建BFC?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 什么是BFC⭐ BFC的作用⭐ 创建BFC的方法⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那些对Web…

TENNECO EDI 项目——X12与XML之间的转换

近期为了帮助广大用户更好地使用 EDI 系统&#xff0c;我们根据以往的项目实施经验&#xff0c;将成熟的 EDI 项目进行开源。用户安装好知行之桥EDI系统之后&#xff0c;只需要下载我们整理好的示例代码&#xff0c;并放置在知行之桥指定的工作区中&#xff0c;即可开始使用。 …

在Java中操作Redis(详细-->从环境配置到代码实现)

在Java中操作Redis 文章目录 在Java中操作Redis1、介绍2、Jedis3、Spring Data Redis3.1、对String的操作3.2、对哈希类型数据的操作3.3、对list的操作3.4、对set类型的操作3.5、对 ZSet类型的数据&#xff08;有序集合&#xff09;3.6、通用类型的操作 1、介绍 Redis 的Java客…

C语言笔试训练【第六天】

大家好&#xff0c;我是纪宁。今天是C语言笔试训练的第6天&#xff0c;加油&#xff01; 往期回顾&#xff1a; C语言笔试训练【第五天】 C语言笔试训练【第四天】 C语言笔试训练【第三天】 C语言笔试训练【第二天】 C语言笔试训练【第一天】 1、以下叙述中正确的是&…

client-go实战之十二:选主(leader-election)

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 本篇概览 本文是《client-go实战》系列的第十二篇&#xff0c;又有一个精彩的知识点在本章呈现&#xff1a;选主(leader-election)在解释什么是选主之前&…

【2023 华数杯全国大学生数学建模竞赛】 A题 隔热材料的结构优化控制研究 问题分析及完整论文

【2023 华数杯全国大学生数学建模竞赛】 A题 隔热材料的结构优化控制研究 问题分析及完整论文 1 题目 A 题 隔热材料的结构优化控制研究 新型隔热材料 A 具有优良的隔热特性&#xff0c;在航天、军工、石化、建筑、交通等高科技领域中有着广泛的应用。 目前&#xff0c;由单…

微服务Ribbon-负载均衡策略和饥饿加载

目录 一、负载均衡策略 1.1 负载均衡策略介绍 1.2 自定义负载均衡策略 二、饥饿加载 &#xff08;笔记整理自bilibili黑马程序员课程&#xff09; 一、负载均衡策略 1.1 负载均衡策略介绍 负载均衡的规则都定义在IRule接口中&#xff0c;而IRule有很多不同的实现类&…

使用巴特沃兹滤波器的1D零相位频率滤波研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Redis布隆过滤器的原理和应用场景,解决缓存穿透

目录 一、redis 二、布隆过滤器 三、缓存穿透问题 四、布隆过滤器解决缓存穿透 一、redis Redis&#xff08;Remote Dictionary Server&#xff09;是一种开源的内存数据存储系统&#xff0c;也是一个使用键值对&#xff08;Key-Value&#xff09;方式的高性能数据库。Red…

Scratch 之 单个角色模糊特效

想给单独一个角色用模糊特效&#xff0c;怎么办&#xff01;&#xff01;&#xff01; 完全不用慌&#xff0c;最近&#xff0c;我做出了超好用的个体模糊特效&#xff0c;用起来超级简单&#xff0c;接下来进入讲解。 1.原理 前几天&#xff0c;我闲来无事&#xff0c;摘下眼镜…