TFTP概述
1.TFTP:简单文件传送协议
2.最初用于引导无盘系统,被设计用来传输小文件
3.特点:
- 基于UDP协议实现
- 不进行用户有效性认证
- octet:二进制模式
- netascii:文本模式
- mail:已经不再支持
5.
TFTP通信过程总结
- 服务器在69号端口等待客户端的请求
- 服务器若批准此请求,则使用临时端口与客户端进行通信
- 每个数据包的编号都有变化(从1开始)
- 每个数据包都要得到ACK的确认如果出现超时,则需要重新发送最后的包(数据或ACK)
- 数据的长度以512Byte传输
- 小于512Byte的数据意味着传输结束
6.程序
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
/*argv[1]:文件名,argv[2]:服务器IP地址*/
//1创建UDP套接字
int socket_client=socket(AF_INET,SOCK_DGRAM,0);
if(socket_client<0)
{
perror("socket_client");
}
//2 标示目的信息
struct sockaddr_in client_addr;//目的地址结构体,定义时使用
bzero(&client_addr,sizeof(client_addr));
client_addr.sin_family=AF_INET;//IP_4
client_addr.sin_port=htons(69);// 服务器端口号,htos与数值处理有关
client_addr.sin_addr.s_addr=inet_addr(argv[2]);//pc机端口号,innet_addr用于转换IP
//构造读请求数据包并发送到69端口
char buf[250]="";
int buf_len;
buf_len=sprintf(buf,"%c%c%s%c%s%c",0,1,argv[1],0,"octet",0);
sendto(socket_client,buf,buf_len,0,(struct sockaddr *)&client_addr,sizeof(client_addr));
//创建下载文件
int fp = open(argv[1],O_RDWR|O_CREAT,0777);
char recvbuf[1024]={0};
char my_atk[4];
int m_length;
struct sockaddr_in from_addr;
socklen_t len=sizeof(from_addr);
while(m_length=recvfrom(socket_client,recvbuf,sizeof(recvbuf),0,(struct sockaddr *)&from_addr,&len)==516)
{
//判断数据操作码
if(recvbuf[0]==0&&recvbuf[1]==3)//CMD=3(数据包)
{
//保存数据到文件
write(fp,recvbuf+4,512);
//构造ACK包并发送到对方的临时端口
my_atk[0]=0;
my_atk[1]=4;
my_atk[2]=recvbuf[2];
my_atk[3]=recvbuf[3];
sendto(socket_client,my_atk,4,0,(struct sockaddr *)&from_addr,sizeof(from_addr));
}
}
//recvfrom(socket_client,recvbuf,strlen(recvbuf),0,(struct sockaddr *)&from_addr,&len);
write(fp,recvbuf+4,512);
my_atk[0]=0;
my_atk[1]=4;
my_atk[2]=recvbuf[2];
my_atk[3]=recvbuf[3];
sendto(socket_client,my_atk,4,0,(struct sockaddr *)&from_addr,sizeof(from_addr));
close(fp);
close(socket_client);
return 0;
}