- 论坛徽章:
- 0
|
TFTP协议是基于udp协议的简单文件传输协议,最早用于引导无盘系统,在网吧比较常见,其数据传输过程及实现原理如下(具体的报文格式这里不在详细介绍):
1、客服端向服务器端发送读写请求(读写报文)
2、服务器端向客服端发送回应信息
3、客服端向服务器端发送确认信息包(ack)
4、服务器段向克服端发送数据包
5、客服端向服务器端发确认信息包(ack)
--------数据包发送结束------
//===============================================================
//The information contained herein is the exclusive property of
//
//or disclosed in whole in part without prior written permission.
//
//ALL RIGHTS RESERVED
//The entire notice above must be reproduced on all authorized
//=============================================================
//=============================================================
// 文件名称:TFTP_cli.c
// 功能描述:TFTP Client
// 维护记录:2009-5-5 V1.0
//=============================================================
#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 fcntl.h>
#include sys/types.h>
#include sys/stat.h>
//=============================================================
// 语法格式: void main(void)
// 实现功能: 主函数,建立一个TFTP Client
// 入口参数: 无
// 出口参数: 无
//=============================================================
int main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_in srvAddr;//创建一个服务器地址
//char *srvIP = argv[1];
char *srvIP ="192.168.220.198";
unsigned short port = 69;//tftp协议默认端口为69
//if(argc
//{
// printf("argument err!\n");
// exit(1);
//}
//if(argc > 2)
//port = atoi(argv[2]);//服务器地址和端口信息初始化
bzero(&srvAddr, sizeof(srvAddr));
srvAddr.sin_family = AF_INET;
srvAddr.sin_port = htons(port);
inet_pton(AF_INET, srvIP, &srvAddr.sin_addr.s_addr);//将main函数中传入的ip信息转换成网络上的big端
sockfd = socket(AF_INET, SOCK_DGRAM, 0);//创建一个client端socket
if(sockfd 0)
{
printf("Invalid socket\n");
exit(1);
}
printf("ready send data to UDP server %s:%d!\n", srvIP, port);
//download_addr();
int fd;
char sendbuf[2048];
char mode[10]="octet";
//size_t len;
char filename[30];
int head_len=0;
printf("input download filename:");
fgets(filename,sizeof(filename),stdin);
filename[strlen(filename)-1]='\0';
if((fd=open(filename,O_RDWR|O_CREAT, 007))0)
{
printf("can not open file %s\n",filename);
}
memset(sendbuf,0,sizeof(sendbuf));
//------------构建一个tftp数据包头部格式;
sendbuf[0]=0;
sendbuf[1]=1;
strcat(sendbuf+2,filename);
strcat(sendbuf+strlen(filename)+3,mode);
head_len=strlen(filename)+strlen(mode)+4;
//printf("head_len=%d\n",head_len);
//--------------开始向服务器发送文件下载请求,并接收数据
char recvbuf[1024];
char ack_data[5];
size_t recvlen;
size_t len;
len=sizeof(srvAddr);
sendto(sockfd, sendbuf, head_len, 0, (struct sockaddr*)&srvAddr, sizeof(srvAddr));
while(1)
{
memset(ack_data,0,sizeof(ack_data));
memset(recvbuf,0,sizeof(recvbuf));
memset(sendbuf,0,sizeof(sendbuf));
if((recvlen = recvfrom(sockfd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*)&srvAddr, &len))>0)
{
memcpy(ack_data,recvbuf,4);//此函数空字符照样可以拷贝
if(ack_data[1]==3) //收到的是数据包
{
write(fd,recvbuf+4,recvlen-4);
ack_data[1]=4;
sendto(sockfd, ack_data, 4, 0, (struct sockaddr*)&srvAddr, sizeof(srvAddr));
}
else if(ack_data[1]==5) //收到的是错误信息包
{
if(ack_data[3]==0)
{
printf("no define!\n");
}
else if(ack_data[3]==1)
{
printf("file not found!\n");
}
else if(ack_data[3]==2)
{
printf("disk full or allocation exceeded!\n");
}
else if(ack_data[3]==4)
{
printf("illegal TFTP operation\n");
}
else if(ack_data[3]==5)
{
printf("unkonw transfer id\n");
}
else if(ack_data[3]==6)
{
printf("file already exists!\n");
}
else if(ack_data[3]==7)
{
printf("no such usr!\n");
}
else if(ack_data[3]==8)
{
printf("unsupported options requested\n");
}
else
{
printf("unknow err!\n");
}
}
else
{
}
}
if(recvlen516)
{
break;
}
//sendbuf[len] = '\0';
//printf("%s", sendbuf);
}
close(sockfd);
return 0;
}
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/94835/showart_1918794.html |
|