一、tftp简介
tftp:简单文件传送协议,最初用于引导无盘系统,被设计用来传输小文件
特点:
基于udp协议实现
不进行用户有效性认证
数据传输模式:
octet:二进制模式
netascii:文本模式
mail:已经不再支持
二、tftp通信过程
1、服务器在69号端口等待客户端的请求
2、服务器若批准此请求,则使用临时端口与客户端进行通信
3、每个数据包的编号都有变化(从1开始)
4、每个数据包都要得到ack的确认如果出现超时,则需要重新发送最后的包(数据或ack)
5、数据的长度以512byte传输
6、小于512byte的数据意味着传输结束
三、协议分析
3.错误码
0 未定义,参见错误信息
1 file not found.
2 access violation.
3 disk full or allocation exceeded.
4 illegal tftp operation.
5 unknown transfer id.
6 file already exists.
7 no such user.
8 unsupported option(s) requested.
代码如下
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc,char *argv[])
{
if(argc!=3){
printf("./a.out server_ip file_name\n");
return 0;
}
//创建socket套接字(基于udp)
int socket_fd = socket(af_inet, sock_dgram, 0);
if(socket_fd<0){
perror("socket");
return 0;
}
//组tftp文件读取请求
unsigned char cmd[128]="";
int len = sprintf(cmd,"%c%c%s%c%s%c",0x00,0x01,argv[2],0,"octet",0);
//将请求cmd发送到服务器69端口
struct sockaddr_in server;
bzero(&server,sizeof(server));
server.sin_family = af_inet;
server.sin_port = htons(69);
inet_pton(af_inet,argv[1],&server.sin_addr.s_addr);
sendto(socket_fd,cmd,len,0,(struct sockaddr *)&server,sizeof(server));
//打开一个本地空文件,将得到的数据写进去
int fd=open(argv[2],o_wronly | o_creat,0666);
if(fd<0){
perror("open");
return 0;
}
//不停读取服务器传过来的文件数据
unsigned short num=0;
while(1){
unsigned char buf[1024]="";
struct sockaddr_in from;
socklen_t from_len = sizeof(from);
int len = recvfrom(socket_fd,buf,sizeof(buf),0,(struct sockaddr *)&from, &from_len);
//判断收到的数据的操作码(必须是00 03表示文件数据)
if(buf[1]==0x03){
//将文件数据写入本地文件中
//防止写入重复数据
if((num 1) == ntohs(*(unsigned short *)(buf 2)))
{
write(fd,buf 4,len-4);
num = ntohs(*(unsigned short *)(buf 2));
printf("recv:%d\n",num);
}
//给服务器发送ack回应
buf[1]=4;
sendto(socket_fd,buf,4,0,(struct sockaddr *)&from,sizeof(from));
if(len<516){
//最后一个文件数据
break;
}
}
}
//关闭套接字
close(socket_fd);
//关闭文件
close(fd);
return 0;
}