当前位置:网站首页>作业8.10 TFTP协议 下载功能
作业8.10 TFTP协议 下载功能
2022-08-11 03:06:00 【不知名大学生M】
TFTP协议 下载功能
实现代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
//打印错误新的宏函数
#define ERR_MSG(msg) do{\ fprintf(stderr, " __%d__ ", __LINE__);\ perror(msg);\ }while(0)
int main(int argc, const char *argv[])
{
if(argc < 4)
{
fprintf(stderr, "请输入IP port\n");
return -1;
}
//将获取到的端口号字符串,转换成整形
int port = atoi(argv[2]);
//创建报式套接字
int sfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
//绑定客户端自身的地址信息结构体 ---> 非必须绑定
//填充服务器的IP地址以及端口号 -->因为客户端要主动发送数据包给服务器
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = inet_addr(argv[1]);
struct sockaddr_in rcv_addrmsg; //存储接收到的数据包来自哪里
socklen_t addrlen = sizeof(rcv_addrmsg);
char buf[128] = ""; //读写请求
char buf2[1024]= ""; //数据包
char buf3[16]=""; //ACK
char *ptr=buf;
short int* pa =(short int*)ptr;
*pa=htons(1); //读写请求的操作码
char *pb=ptr+2; //读写请求的文件名
strcpy(pb,"5.png");
char *pc =pb+strlen(pb);
char *pd=pc+1;
strcpy(pd,"octet"); //读写请求的模式
size_t size=2+strlen(pb)+1+strlen("octet")+1; //读写请求长度
//将数据包发送给服务器,所以地址信息结构体需要填服务器的信息
if(sendto(sfd, buf,size,0,(struct sockaddr*)&sin, sizeof(sin)) < 0)
{
ERR_MSG("sendto");
return -1;
}
//printf("sendto success\n");
short int num=1; //块编号
ssize_t res; //数据包成功读取的字节数
int fd=open(argv[3],O_WRONLY|O_TRUNC|O_CREAT,0777); //打开指定文件
if(fd<0)
{
ERR_MSG("open");
return -1;
}
while(1)
{
bzero(buf2, sizeof(buf2)); // 数据包清空
//接收服务器发送过来的数据包
if((res=recvfrom(sfd, buf2, sizeof(buf2), 0, (struct sockaddr*)&rcv_addrmsg,&addrlen))< 0)
{
ERR_MSG("recvfrom");
return -1;
}
char *ptr2=buf2;
short int *err;
if(ntohs(*(err=(short int*)ptr2))==5) //操作码等于5,ERROR
{
printf("error:%s\n",(char*)(err+2)); //打印差错信息
return -1;
}
//操作码不为5,即为3,是数据包,ptr2指向数据包首地址
write(fd,ptr2+4,res-4); //数据包的数据写入文件
short int *pa2=(short int*)ptr2; //获取服务器发过来的块编号
if(ntohs(*(pa2+1))!=num) //比较块编号是否相同,即顺序正确
{
continue;
}
num++;
bzero(buf3, sizeof(buf3)); //清空ACK
char *ptr3=buf3; //ACK首地址
short int* pa3=(short int*)ptr3;
*pa3=htons(4); //ACK操作码
*(pa3+1)=*(pa2+1); //ACK块编号
//将ACK发送给服务器
if(sendto(sfd, buf3,4,0,(struct sockaddr*)&rcv_addrmsg, addrlen) < 0)
{
ERR_MSG("sendto");
return -1;
}
if(res<516) //数据包里的数据小于512字节
{
break; //退出循环
}
}
printf("下载完成\n");
//关闭套接字
close(sfd);
return 0;
}
运行结果
服务器
IP地址:192.168.31.22
端口:69
从服务器下载文件5.png




边栏推荐
- 《人生若如初见》命运多舛,人物饱满,朱亚文角色反差太惊喜
- [BX] and loop
- Goodbye Chongqing paper invoices!The issuance of electronic invoices for accommodation expenses will soon completely replace the invoices of hotels, catering and gas stations
- “京台高铁”亮相百度地图,真能在2035年建成吗?
- (Nips-2015)空间变换器网络
- Detailed explanation of new features of ES advanced function syntax
- Entity to Vo conversion
- (CVPR - 2017) in depth and potential body learning context awareness feature for pedestrian recognition
- The practice of alibaba data synchronization component canal
- 2022制冷与空调设备运行操作考试试题模拟考试平台操作
猜你喜欢
随机推荐
成都纸质发票再见!开住宿费电子发票即将全面取代酒店餐饮加油站发票
四大组件---ContentResolver
Entity to Vo conversion
Goodbye Chongqing paper invoices!The issuance of electronic invoices for accommodation expenses will soon completely replace the invoices of hotels, catering and gas stations
IDE编译报错:Dangling metacharacter
js中的this问题
ESP32的环境配置(arduino arduino2.0 VScode platform哪个好用?)
ES6进阶 字符串处理新特性
Ten Advanced Concepts of SQL Development
互换性与测量技术-公差原则与选用方法
Ninjutsu_v3_08_2020-安全渗透系统安装
阿里低代码框架 lowcode-engine 之自定义物料篇
comp3331-9331-21t2-midterm复习
Vim and copy and paste from the outside (don't need to install the plugin)
SQL 开发的十个高级概念
2022制冷与空调设备运行操作考试试题模拟考试平台操作
2022茶艺师(中级)考试试题及模拟考试
[4G/5G/6G专题基础-154]: 5G无线准入控制RAC(Radio Admission Control)
[机缘参悟-66]:怎样才能让别人愿意帮你:利益共享法则、“大道”、“人性”
深度学习-第二次








