Chinaunix首页 | 论坛 | 博客
  • 博客访问: 48372
  • 博文数量: 13
  • 博客积分: 563
  • 博客等级: 下士
  • 技术积分: 140
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-18 14:45
文章存档

2014年(1)

2011年(2)

2010年(2)

2009年(8)

分类: LINUX

2009-09-06 19:29:26

   依据TFTP协议的规定,实现通过TFTP来实现文件的传输功能。
TFTP Server:
实现功能:实现TFTP服务器,可以让用户下载文件
命令:   tftps rootdir(请求的文件路径)
实现思路:
监听69端口
接收到数据后,fork子进程服务该客户端
分析客户端的请求报文,检查是否有扩展参数
如果有扩展参数,则回应OACK,并等待客户端对OACK做回应
启动传输数据
文件传输结束后子进程退出

tftps.c


int main(int argc,char **argv)
{
    
int server_sockfd,client_sockfd;
    
int server_len,client_len;
    
struct sockaddr_in server_address;
    
struct sockaddr_in client_address;
    
char recv_buf[516] = {};
    
char send_buf[516] = {};
    
char recv_cmd[4] = {};
    
int byte;
    
int n = 0;
    
int pid,fd;

    server_sockfd
= socket(AF_INET,SOCK_DGRAM,0);
    bzero
(&server_address,sizeof(server_address));
    server_address
.sin_family = AF_INET;
    server_address
.sin_addr.s_addr = inet_addr("192.168.220.59");

//我的PC机IP地址
    server_address
.sin_port = htons(69);
    server_len
= sizeof(server_address);
    
bind(server_sockfd,(struct sockaddr *)&server_address,server_len);

    
if((byte = recvfrom(server_sockfd,recv_buf,516,0,(struct sockaddr *)&client_address,sizeof(struct sockaddr))) == -1)
    
{
        
perror("recvfrom");
        
exit(0);
    
}

//创建一个进程来分析收到的报文信息
    
if((pid = fork()) == 0)
    
{
        
if(recv_buf[1] == 1)  //为下载文件请求
        
{
            
printf("this is a read request:\n");
            
if((fd = open(recv_buf[2],O_RDONLY)) < 0)
            
{
                
perror("open");
                
exit(0);
            
}


            
while(1)
            
{
                
recvfrom(server_sockfd,recv_cmd,4,0,(struct sockaddr *)&client_address,sizeof(struct sockaddr));
                
read(fd,send_buf+4,sizeof(send_buf+4));

//将文件内容读入数据区
                send_buf
[1] = 3;

//构造报文
                
if((byte = sendto(server_sockfd,send_buf,516,0,(struct sockaddr *)&client_address,sizeof(struct sockaddr))) == 516)
                
{
                    
sendto(server_sockfd,send_buf,4,0,(struct sockaddr *)&client_address,sizeof(struct sockaddr));
                    send_buf
[3]++;
                
}

//TFTP每次发送512个字节,附带四个字节的报文信息,小于516时就代表文件传输完毕
                
else
                    
exit(0);
            
}
        
}
        
if (recv_buf[1] == 2) //为上传文件请求
        
{
            
printf("this is a write request:\n");
            
if((fd = open(recv_buf[2],O_RDWR|O_CREAT)) < 0)
            
{
                
perror("open");
                
exit(0);
            
}
            
while(1)
            
{
                
recvfrom(server_sockfd,recv_cmd,4,0,(struct sockaddr *)&client_address,sizeof(struct sockaddr));
                
recvfrom(server_sockfd,recv_buf,512,0,(struct sockaddr *)&client_address,sizeof(struct sockaddr));
                
write(fd,send_buf+4,sizeof(send_buf+4));
                send_buf
[1] = 3;
                
if((byte = sendto(server_sockfd,send_buf,516,0,(struct sockaddr *)&client_address,sizeof(struct sockaddr))) == 516)
                
{
                    
sendto(server_sockfd,send_buf,4,0,(struct sockaddr *)&client_address,sizeof(struct sockaddr));
                    send_buf
[3]++;
                
}
                
else
                    
exit(0);
            
}
        
}
        
close(fd);
    
}
    
else
        
return 0;
}
        
            


TFTP Client:
实现功能:通过tftp下载文件
命   令:tftpc ip file
实现思路:
构造请求报文,送至服务器
等待服务器回应
分析服务器回应
循环接收数据,直到接收到的数据包小于标准数据包
tftpc.c

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <fcntl.h>

int main(int argc,char **argv)
{
    
int sockfd;
    
struct sockaddr_in server;
    
char read_cmd[100] = {};
    
char buf[516]="";
    
char *str;
    
int addrlen = sizeof(server);
    
int fd,rew,recv,read_num,send_num;
    
int n = 0,num;
    
char filename[100] = {};
    
    
if(argc == 1)
    
{
        
printf("ERROR:please input a filename:\n");
        
exit(0);
    
}
    
else if(argc == 2)
    
{
        
strcpy(filename,argv[1]);
    
}
    bzero
(&server, sizeof(struct sockaddr_in));
    server
.sin_family = AF_INET;
    server
.sin_port = htons(69);
    server
.sin_addr.s_addr = inet_addr("192.168.220.59");
    
    
printf("please input read?write:1 or 2: ");
    
scanf("%d",&num);
    rew
= sprintf(read_cmd,"%c%c%s%c%s%c",0,num,filename,0,"octet",0);
    sockfd
= socket(AF_INET, SOCK_DGRAM, 0);
    
if(sockfd < 0)
    
{
        
perror("Invalid socket");
        
exit(1);
    
}

    
sendto(sockfd, read_cmd, rew, 0, (struct sockaddr*)&server, sizeof(struct sockaddr));
    
if((fd = open(filename, O_RDWR|O_CREAT))<0)    
    
{        
        
perror("open");
        
exit(1);
    
}

    
if (num == 1)
    
{
        num
= 0;
        
do{
            bzero
(buf,sizeof(buf));
            
recv = recvfrom(sockfd, buf, 516, 0, (struct sockaddr*)&server, &addrlen);    
            
write(fd, buf+4, 512);
            
if(n == 255)
            
{
                num
++;
                n
= -1;
            
}
            rew
= sprintf(read_cmd,"%c%c%c%c",0,4,num,++n);
            
sendto(sockfd, read_cmd, rew, 0, (struct sockaddr*)&server, sizeof(struct sockaddr));
        
}while(recv == 516);
    
}
    
    
if( num == 2)
    
{
        
do{
            bzero
(buf,sizeof(buf));
            
recvfrom(sockfd, buf, 4, 0, (struct sockaddr*)&server, &addrlen);        
            buf
[1] = 3;
            
if((unsigned char)buf[3]==255)
            
{
                buf
[2]++;
            
}
            buf
[3]++;
            read_num
= read(fd,buf+4,512);
            
printf("%d\n",send_num);
            send_num
= sendto(sockfd, buf, read_num+4, 0, (struct sockaddr*)&server, sizeof(struct sockaddr));
        
}while(read_num==512);
    
}                    
    
close(fd);
    
return 0;
}

阅读(1219) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~