网络编程day03(UDP中的connect函数、tftp)

news2024/9/28 9:25:01

今日任务:tftp的文件上传下载(服务端已经准备好)

服务端(已上传)

 客户端:

代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <strings.h>
#include <fcntl.h>

//自定义报错提示
#define ERR_MSG(msg) do{\
	fprintf(stderr,"__%d__",__LINE__);\
	perror(msg);\
}while(0)

//#define SER_PORT 69
//#define SER_IP "192.168.125.74"
#define SER_PORT 69
#define SER_IP "192.168.125.225"
int do_upload(int cfd,struct sockaddr_in addr);
int do_download(int cfd,struct sockaddr_in addr);
int main(int argc, const char *argv[])
{
	//1.创建socket套接字
	int cfd=socket(AF_INET,SOCK_DGRAM,0);
	if(cfd<0){
		ERR_MSG("socket");
		return -1;
	}
	puts("socket success");


	//3.接受和发送消息
	//目标地址信息
	struct sockaddr_in addr;
	addr.sin_family=AF_INET;
	addr.sin_port=htons(SER_PORT);
	addr.sin_addr.s_addr=inet_addr(SER_IP);
	socklen_t addrlen=sizeof(addr);

	//记录接受信息的目标地址信息
	struct sockaddr_in recv_addr;
	socklen_t recv_addrlen=sizeof(recv_addr);

	while(1){
		puts("---------------------------------");
		puts("------------1.上传---------------");
		puts("------------2.下载---------------");
		puts("------------3.退出---------------");
		puts("---------------------------------");
		puts("请选择>>");
		char choice;
		choice=getchar();
		while(getchar()!='\n');//循环吸收垃圾字符
		switch(choice){
		case '1':
			do_upload(cfd,addr);
			break;
		case '2':
			puts("download");
			do_download(cfd,addr);
			break;
		case '3':
			goto END;
		}
	}
END:

	/*
	   char buf[128];
	   while(1){

	   printf("请输入>>>");
	   fgets(buf,sizeof(buf),stdin);
	   buf[strlen(buf)-1]='\0';



	   int send_res=sendto(cfd,buf,sizeof(buf),0,(struct sockaddr*)&addr,addrlen);
	   if(send_res<0){
	   ERR_MSG("sendto");
	   return -1;
	   }
	   puts("sendto success");
	   if(strcmp(buf,"quit")==0)
	   break;

	   bzero(buf,sizeof(buf));
	   int recv_res=recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&recv_addr,&recv_addrlen);
	   if(recv_res<0){
	   ERR_MSG("recvfrom");
	   return -1;
	   }
	   puts("recvfrom success");
	   printf("[%s:%d]:%s\n",inet_ntoa(recv_addr.sin_addr),ntohs(recv_addr.sin_port),buf);	

	   }

*/
	//4.关闭
	close(cfd);
	return 0;
}
int do_upload(int cfd,struct sockaddr_in addr){
	printf("请输入要上传的文件名.>>>");
	char name[20]="";
	scanf("%s",name);
	while(getchar()!=10);

	//组下载协议
	char buf[516]="";
	//操作码
	unsigned short *p1=(unsigned short*)buf;
	*p1=htons(2);
	//文件名
	char *p2=buf+2;
	strcpy(p2,name);
	//0
	//模式
	char *p4=p2+strlen(name)+1;
	strcpy(p4,"octet");
	//0
	int size=2+strlen(name)+1+strlen(p4)+1;
	//printf("buf==%s;size==%d",buf,size);
	//发送协议给服务器
	if(sendto(cfd,buf,size,0,(struct sockaddr*)&addr,sizeof(addr))<0){
		ERR_MSG("sendto");
		return -1;
	}
	puts("send upload protocal success");
	//打开一个文件,输入
	int fd=open(name,O_RDONLY);
	if(open<0){
		ERR_MSG("open");
		return -1;
	}
	unsigned short bNum=1;
	//重新定义一个地址的结构体,接受服务端传来的临时地址
	struct sockaddr_in dest_addr;
	socklen_t addrlen=sizeof(dest_addr);
	if(recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&dest_addr,&addrlen)<0){
		ERR_MSG("recvfrom");
		return -1;
	}

	while(1){
		//组包:操作码+块编号+数据
		bzero(buf,sizeof(buf));
		unsigned short *opNum=(unsigned short*)buf;
		*opNum=htons(3);
		unsigned short *blockNum=opNum+1;
		*blockNum=htons(bNum);
		char* msg=buf+4;
		int read_res=read(fd,msg,512);
		if(read<0){
			ERR_MSG("read");
		}
		//发包
		ssize_t sendto_res=sendto(cfd,buf,sizeof(buf),0,(struct sockaddr*)&dest_addr,addrlen);
		if(sendto_res<0){
			ERR_MSG("sendto");
			return -1;
		}
		printf("sendto_res=%ld\n----",sendto_res);

		//接受ack
		if(recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&dest_addr,&addrlen)<0){
			ERR_MSG("recvfrom");
			return -1;
		}
		
		opNum=(unsigned short*)buf;
		blockNum=opNum+1;
		if(ntohs(*opNum)==5){
			puts("操作码错误");
			printf("%d %d:%s",ntohs(*opNum),ntohs(*blockNum),msg);
		}else if(ntohs(*opNum)==4){
			if(ntohs(*blockNum)==bNum){
				puts("ACK correct");
			}else{
				puts("ACK incorrect");
				return -1;
			}
		}
		bNum++;

		if(read_res<512){
			printf("bNUm==%d\n",bNum);
			puts("upload done");
			break;
		}
	
	}
	close(fd);

}
int do_download(int cfd,struct sockaddr_in addr){
	printf("请输入要下载的文件名.>>>");
	char name[20]="";
	scanf("%s",name);
	while(getchar()!=10);

	//组下载协议
	char buf[516]="";
	//操作码
	unsigned short *p1=(unsigned short*)buf;
	*p1=htons(1);
	//文件名
	char *p2=buf+2;
	strcpy(p2,name);
	//0
	//模式
	char *p4=p2+strlen(name)+1;
	strcpy(p4,"octet");
	//0
	int size=2+strlen(name)+1+strlen(p4)+1;
	//printf("buf==%s;size==%d",buf,size);
	//发送协议给服务器
	if(sendto(cfd,buf,size,0,(struct sockaddr*)&addr,sizeof(addr))<0){
		ERR_MSG("sendto");
		return -1;
	}
	puts("send download protocal success");
	//新建打开一个文件,等下写入
	int fd=open(name,O_WRONLY|O_CREAT|O_TRUNC,0664);
	if(fd<0){
		ERR_MSG("open");
		return -1;
	}
	//重新定义一个地址的结构体,接受服务端传来的临时地址
	struct sockaddr_in dest_addr;
	socklen_t addrlen=sizeof(dest_addr);
	while(1){
		//接受数据包
		int recv_res=recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&dest_addr,&addrlen);
		if(recv_res<0){
			ERR_MSG("recvfrom");
			return -1;
		}
		unsigned short* opNum=(unsigned short*)buf;
		unsigned short* blockNum=opNum+1;
		char * msg=(char *)(blockNum+1);
		if(ntohs(*opNum)==5){
			puts("操作码错误");
			printf("%d %d:%s",ntohs(*opNum),ntohs(*blockNum),msg);
		}else if(ntohs(*opNum)==3){
			int wr_res=write(fd,msg,recv_res-4);
			if(wr_res<0){
				ERR_MSG("write");
			}else if(wr_res<512){
				puts("recvfrom done");
				break;
			}
		}

		//组ACK包,吾把buf当做ack来使
		*opNum=htons(4);

		//回复ACK包
		sendto(cfd,buf,4,0,(struct sockaddr*)&dest_addr,addrlen);
		bzero(buf,sizeof(buf));
	}


	//
}

运行结果:

不知道是网络的问题还是代码的问题,上传很慢,代码很快正常运行结束了,但是tftp服务端下载到win上很慢,7kb的也要5s以上

今日思维导图

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

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

相关文章

全球南方《乡村振兴战略下传统村落文化旅游设计》许少辉八一新枝——2023学生开学季辉少许

全球南方《乡村振兴战略下传统村落文化旅游设计》许少辉八一新枝——2023学生开学季辉少许

QT实现简易时钟

头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPaintEvent> #include <QDebug> #include <QPainter> #include <QTimerEvent> #include <QTimer> #include <QTime>QT_BEGIN_NAMESPACE namespace Ui { cl…

51单片机项目(13)——基于51单片机的智能台灯protues仿真

本次设计&#xff0c;使用protues软件进行仿真&#xff0c;详情如下&#xff1a; 1.输入部分:由热释电红外传感器、光敏传感器、超声波测距传感器所构成的子电路组成。 2.输出模块:由1602液晶显示及其蜂鸣器报警系统组成。 3.中央处理器:主要有AT89C52单片机构成。 4.工作过…

C++ PrimerPlus 复习 第八章 函数探幽

第一章 命令编译链接文件 make文件 第二章 进入c 第三章 处理数据 第四章 复合类型 &#xff08;上&#xff09; 第四章 复合类型 &#xff08;下&#xff09; 第五章 循环和关系表达式 第六章 分支语句和逻辑运算符 第七章 函数——C的编程模块&#xff08;上&#xff…

一、Stable Diffusion WebUI 安装

Mac 配置 类别配置机型Macbook pro m2核总数12 核中央处理器、38 核图形处理器和 16 核神经网络引擎内存64 G系统Sonoma 安装 Homebrew 打开终端执行&#xff08;使用了国内镜像源安装&#xff09; /bin/bash -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/r…

深入理解HttpSecurity的设计

文章目录 HttpSecurity的应用HttpSecurity的类图结构SecurityBuilder接口AbstractConfiguredSecurityBuilderadd方法doBuild方法 HttpSecurity HttpSecurity的应用 在上文介绍了基于配置文件的使用方式以及实现细节&#xff0c;如下&#xff1a; 也就是在配置文件中通过 secur…

javascript使用正则表达式去除字符串中括号的方法

如下面的例子&#xff1a; (fb6d4f10-79ed-4aff-a915-4ce29dc9c7e1,39996f34-013c-4fc6-b1b3-0c1036c47119,39996f34-013c-4fc6-b1b3-0c1036c47169,39996f34-013c-4fc6-b1b3-0c1036c47111,2430bf64-fd56-460c-8b75-da0a1d1cd74c,39996f34-013c-4fc6-b1b3-0c1036c47112) 上面是前…

华为HCIA(六)

LACPDU中携带接口优先级&#xff0c;系统MAC地址&#xff0c;设备优先级 Mac-vlan命令是配置基于MAC地址的VLAN 二层ACL匹配源目MAC二层协议类型等 HTTP为超文本传输协议&#xff0c;用于网页访问 二层组网指的是AC与AP同在一个网段内 IPV6全球单播地址 华为OSPF内部路由…

Cesium 地球(2)-瓦片创建

Cesium 地球(2)-瓦片创建 QuadtreePrimitive代码执行4个步骤: step1: update()step2: beginFrame()step3: render()step4: endFrame() 但并不是瓦片的创建步骤。 1、创建 QuadtreeTile 基于 step3: render() step3: render()┖ selectTilesForRendering()在 selectTilesFo…

CentOS 7 制作openssl 1.1.1w 版本rpm包 —— 筑梦之路

源码下载地址&#xff1a; https://www.openssl.org/source/openssl-1.1.1w.tar.gz 参考之前的文章&#xff1a; openssl 1.1.1L /1.1.1o/1.1.1t rpm包制作——筑梦之路_openssl的rpm包_筑梦之路的博客-CSDN博客 直接上spec文件&#xff1a; Name: openssl Version: 1.1…

《IP编址与路由:网络层的关键技术》

前言&#xff1a; 在TCP/IP协议栈中&#xff0c;网络层位于第三层&#xff0c;起到了承上启下的关键作用。它不仅负责处理来自数据链路层和传输层的请求&#xff0c;还需确保数据包的正确转发。本文将深入探讨IP编址与路由的相关知识&#xff0c;帮助您更好地理解网络层的重要性…

视觉Transformer在低级视觉领域的研究综述

视觉Transfomer的基本原理 在图像处理过程中&#xff0c;ViT首先将输入的图片分成块&#xff0c;对其进行线性的编码映射后排列成一堆的向量作为编码器的输入&#xff0c;在分类任务中会在这个一维向量加入了一个可学习的嵌入向量用作分类的类别预测结果表示&#xff0c;最后通…

Java:JSR 310日期时间体系LocalDateTime、OffsetDateTime、ZonedDateTime

JSR 310日期时间体系&#xff1a; LocalDateTime&#xff1a;本地日期时间OffsetDateTime&#xff1a;带偏移量的日期时间ZonedDateTime&#xff1a;带时区的日期时间 目录 构造计算格式化参考文章 日期时间包 import java.time.LocalDateTime; import java.time.OffsetDateT…

盲水印接口,版权保护,防止篡改

添加水印&#xff0c;水印生成&#xff0c;获取水印&#xff0c;隐性水印&#xff0c;版权保护&#xff0c;防止篡改&#xff0c;数字媒体分发&#xff0c; 数字取证&#xff0c;水印生成 一、接口介绍 通过上传原始图片和水印图,生成带有隐性水印图的图片。既保持图片的美观…

算法题必备基础技巧(C++版)

最近可能要参加秋招面试........最近还要顺便复习整理一下之前的一些技巧&#xff0c;整理归纳一下。倒不是说放弃考研了&#xff0c;而是尽可能找一个普通的工作保底吧...... 一.函数模板 模板&#xff0c;顾名思义&#xff0c;任何类型都可以套用&#xff0c;分享一个打印任…

【数据分享】2023年全国地级市点位数据(免费获取\shp格式\excel格式)

地级市点位数据是我们各项研究中经常使用到的数据&#xff0c;在之前的文章中我们分享过2022年度的地级市及以上城市的点位数据&#xff08;可查看之前的文章获悉详情&#xff09;。本次我们带来的是2023年度的全国范围的地级市及以上城市的点位数据&#xff0c;点位位置为市政…

【Linux 服务器运维】定时任务 crontab 详解 | 文末送书

文章目录 前言一、crontab 介绍1.1 什么是 crontab1.2 crontab 命令工作流程1.3 Linux 定时任务分类 二、crontab 用法详解2.1 crond 服务安装2.2 crontab 文件内容分析2.3 crontab 命令用法2.3.1 查看定时任务列表2.3.2 编辑/创建定时任务2.3.3 删除定时任务2.3.4 其他 cronta…

NI SCXI-1000 编码器模块

NI SCXI-1000 是 NI&#xff08;National Instruments&#xff09;生产的编码器模块&#xff0c;通常用于工业自动化和控制系统中&#xff0c;以采集和处理编码器信号&#xff0c;用于测量和监测旋转或线性位置。以下是该模块的一些主要产品特点&#xff1a; 编码器输入&#x…

linux内核分析:进程通讯方式

信号 一旦有信号产生,我们就有下面这几种,用户进程对信号的处理方式。 1.执行默认操作。Linux 对每种信号都规定了默认操作,例如,上面列表中的 Term,就是终止进程的意思。Core 的意思是 Core Dump,也即终止进程后,通过 Core Dump 将当前进程的运行状态保存在文件里面…

day1| 704. 二分查找、27. 移除元素

704. 二分查找 题目链接&#xff1a;https://leetcode.cn/problems/binary-search/ 文档讲解&#xff1a;https://programmercarl.com/0704.%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE.html 视频讲解&#xff1a;https://www.bilibili.com/video/BV1fA4y1o715 1、二分法的前提 这道…