- 论坛徽章:
- 0
|
依据TFTP协议的规定,实现通过TFTP来实现文件的传输功能。[color="#CC3333"]TFTP Server:实现功能:实现TFTP服务器,可以让用户下载文件命令: tftps [color="#009999"]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");
[color="#0000CC"]//我的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);
}
[color="#0000CC"]//创建一个进程来分析收到的报文信息
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);
}
[color="#0000CC"]
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));
[color="#0000CC"]//将文件内容读入数据区
send_buf[1] = 3;
[color="#0000CC"]//构造报文
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]++;
}
[color="#0000CC"]//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;
}
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/103431/showart_2046719.html |
|