TFTP通信

一、TFTP概述

      TFTP是一个传输文件的简单协议,通常使用UDP协议而实现,它只能从文件服务器上获得或写入文件,不能列出目录,不进行认证,它传输8位数据。传输中有三种模式:netascii,这是8位的ASCII码形式,另一种是octet,这是8位源数据类型;最后一种mail已经不再支持,它将返回的数据直接返回给用户而不是保存为文件。任何传输起自一个读取或写入文件的请求,这个请求也是连接请求。如果服务器批准此请求,则服务器打开连接,数据以定长512字节传输。每个数据包包括一块数据,服务器发出下一个数据包以前必须得到客户对上一个数据包的确认。如果一个数据包的大小小于512字节,则表示传输结束。如果数据包在传输过程中丢失,发出方会在超时后重新传输最后一个未被确认的数据包。通信的双方都是数据的发出者与接收者,一方传输数据接收应答,另一方发出应答接收数据。

二、TFTP通信过程

      1、服务器在69号端口等待客户端的请求
      2、服务器若批准此请求,则使用临时端口与客户端进行通信
      3、每个数据包的编号都有变化(从1开始)
      4、每个数据包都要得到ACK的确认如果出现超时,则需要重新发送最后的包(数据或ACK)
      5、数据的长度以512Byte传输
      6、 小于512Byte的数据意味着传输结束

三、TFTP协议

      操作码:1 — 读请求

                    2 — 写请求

                    3 — 数据报

                    4 — 数据确认

                    5 — 错误信息

                    6 — 选项确认

      注意:上面的 0 代表的是 '\0'。

四、ubuntu12.04 配置 TFTP

      1、安装TFTP软件

            sudo    apt-get    install    tftp-hpa    tftpd-hpa

            注意:tftp-hpa是客户端,tftpd-hpa是服务器端

      2、建立tftpboot 目录,作为服务器的目录

            sudo mkdir    ~/tftpboot

            注意:释放权限:(服务器目录,需要设置权限为 777,chomd 777)

            sudo chmod 777    ~/tftpboot

      3、配置TFTP服务器 

            sudo gedit /etc/default/tftpd-hpa

            将原来的内容

     

      修改为

     

      4、重新启动TFTP服务

            sudo service tftpd-hpa restart

      5、测试

            $ cd  ~/tftpboot 

            $ echo "hello  tftp  service"  >>  a.txt

            $ cd  ~

            $ echo  "hello tftp  service, put  to  tftp  service"  >>  b.txt

            $ tftp  localhost

            tftp>  get  a.txt

            tftp>  put  b.txt

      注意:其中get是获取文件,put是将文件上传到TFTP服务器上。

五、TFTP上传下载程序

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
	unsigned short port=69;
	char filename[20]="";
	char type[10]="";
	char req_cmd[512]="";
	char *server_ip=NULL;
	int fd;

	int sockfd;
	if(argc!=2)
	{
		printf("\e[31m%s%s\e[0m\n","Cmd error!\n","Please input server IP");
		exit(-1);
	}
	server_ip=argv[1];
	sockfd=socket(AF_INET,SOCK_DGRAM,0);
	if(sockfd<0)
	{
		perror("socket");
		exit(-1);
	}

 	struct sockaddr_in server_addr;
	bzero(&server_addr,sizeof(server_addr));
	server_addr.sin_family=AF_INET;
	server_addr.sin_port=htons(port);
	inet_pton(AF_INET,server_ip,&server_addr.sin_addr);
	socklen_t addr_len=sizeof(server_addr);

	printf("\e[31m%s\e[0m","Please input Type(write or read):");
	scanf("%s",type);
	printf("\e[31m%s\e[0m","Please input filename:");
	scanf("%s",filename);

	if(!strcmp(type,"read"))
	{
		if((fd=open(filename,O_WRONLY|O_CREAT,0755))==-1)
		{
			perror("open");
			exit(-1);
		}
		int ret=sprintf(req_cmd,"%c%c%s%c%s%c",0,1,filename,0,"octet",0);
		sendto(sockfd,req_cmd,ret,0,(struct sockaddr *)&server_addr,sizeof(server_addr));
		while(1)
		{
			char buf[1024]="";

			int ret=recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&server_addr,&addr_len);
			if(buf[1]==3)
			{
				char ack_cmd[20]="";
				write(fd,buf+4,ret-4);
				int ack_ret=sprintf(ack_cmd,"%c%c%c%c",0,4,buf[2],buf[3]);
				sendto(sockfd,ack_cmd,ack_ret,0,(struct sockaddr *)&server_addr,sizeof(server_addr));
			}
			if(ret<516)
			{
				close(fd);
				break;
			}
		}
	}
	else if(!strcmp(type,"write"))
	{
		if((fd=open(filename,O_RDONLY))==-1)
		{
			perror("open");
			exit(-1);
		}
		int ret_cmd=sprintf(req_cmd,"%c%c%s%c%s%c",0,2,filename,0,"octet",0);
		sendto(sockfd,req_cmd,ret_cmd,0,(struct sockaddr *)&server_addr,sizeof(server_addr));
		while(1)
		{
			char buf[516]="";
			static int num=0;
			num++;

			recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&server_addr,&addr_len);
			buf[1]=3;
			buf[2]=num/256;
			buf[3]=num%256;
			int ret=read(fd,buf+4,sizeof(buf)-4);
			if(ret==0)
			{
				close(fd);
				break;
			}
			sendto(sockfd,buf,ret+4,0,(struct sockaddr *)&server_addr,sizeof(server_addr));
		}
	}
	close(sockfd);
	return 0;
}


 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值