基于UDP的TFTP文件传输
//主函数
#include "head.h"
int main(int argc, const char *argv[])
{
//创建报式套接字
int cli_fd;
cli_fd = socket(AF_INET,SOCK_DGRAM,0);
if(cli_fd<0)
{
ERR_MSG("socket");
return -1;
}
//准备发送对象的信息地址结构体
struct sockaddr_in ser_sin;
ser_sin.sin_family = AF_INET;
ser_sin.sin_port = htons(PORT);
ser_sin.sin_addr.s_addr = inet_addr(IP);
//下载
if(DownLoad(cli_fd,ser_sin)<0)
{
printf("DownLoad failed\n");
}
//关闭套接字流指针
close(cli_fd);
return 0;
}
//头文件
#ifndef __HEAD_HH__
#define __HEAD_HH__
#include <quick.h>
#define PORT 69
#define IP "192.168.1.8"
int DownLoad(int cli_fd,struct sockaddr_in ser_sin);
#endif
//子函数
#include "head.h"
//下载
#include "head.h"
//下载
int DownLoad(int cli_fd,struct sockaddr_in ser_sin)
{
//从终端中获取下载文件名
printf("please enter a filename : ");
char filename[128]="";
fgets(filename,sizeof(filename),stdin);
filename[strlen(filename)-1]=0;
//以写的方式打开文件
int fd_w = open(filename,O_WRONLY|O_CREAT|O_TRUNC,0664);
if(fd_w<0)
{
perror("open");
return -1;
}
printf("file has been opened\n");
//创建地址信息结构体,用来存放服务器临时地址信息
struct sockaddr_in tem_sin;
socklen_t addrlen;
//包装读写请求字符串
char readask[128]="";
short *rp1=(short *)readask;
*rp1 = htons(1);
char *rp2=readask+2;
strcpy(rp2,filename);
char *rp3=rp2+strlen(filename)+1;
strcpy(rp3,"octet");
//变量
char dload[516]="";
ssize_t res=0;
size_t len=4+strlen(rp2)+strlen(rp3);
//发送读写请求
res = sendto(cli_fd,readask,len,0,(struct sockaddr*)&ser_sin,sizeof(ser_sin));
if(res<0)
{
printf("send ask to server failed\n");
return -1;
}
printf("read ask sended\n");
while(1)
{
//接收数据包
bzero(dload,sizeof(dload));
res = recvfrom(cli_fd,dload,sizeof(dload),0,(struct sockaddr *)&tem_sin,&addrlen);
if(res<0)
{
printf("receive failed\n");
return -1;
}
printf("receive finished\n");
//解析数据,包括临时地址信息
//*dload = ntohs(*dload);
short *wp1 = (short *)dload;
*wp1 = ntohs(*wp1);
short *wp2 = wp1+1;
*wp2 = ntohs(*wp2);
char *wp3 = dload+4;
//包装ACK返回信息字符串
char ack[4]="";
short *ap1 = (short *)ack;
*ap1 = htons(4);
short *ap2 = ap1+1;
*ap2 = htons(*wp2);
//返回ACK读取信息完毕信息
if(sendto(cli_fd,ack,4,0,(struct sockaddr*)&tem_sin,sizeof(ser_sin))<0)
{
printf("send ACK to server failed\n");
return -1;
}
printf("ACK sended\n");
//将读取的数据写入文件中
write(fd_w,wp3,res-4);
//判断是否读取完毕
printf("res = %ld\n",res);
if(res < 516)
{
printf("DownLoad finished\n");
break;
}
}
return 0;
}
day3
于 2023-08-13 21:54:55 首次发布