我们或许都听到过,TFTP(Trivial File Transfer Protocol,简单文件传输协议)是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂、开销不大的文件传输服务。
本文就简单的叙述下tftp的小文件传输功能以及客户端对服务器的列表功能。
之前就一直很纳闷,我们经常在网上下载什么东西或者从别处传输一个文件,具体是怎么实现的呢?于是乎,翻查一些资料,加上自己对网络编程的逐步加深,所以功夫不负有心人,还算是大致的完成了下。
本例程实现的功能呢? 就是实现客户端对服务器端提供的文件上传与下载功能,还有对服务器端目录的显示功能,好了,请阅读下面的编程实现部分:
首先是服务器端:
#include<head.h>
typedef struct
{
int type;
int size;
char mtxt[1024];
}MSG;
#define PUT_FILE 10
#define GET_FILE 20
#define LIST_DIR 30
#define NEXIST_FILE 40
#define YEXIST_FILE 50
void handler_signal(int signum)
{
waitpid(-1,NULL,WNOHANG);
printf("CHild process over!\n");
}
void do_put(int sockfd,MSG *pmsg)
{
int fd;
fd = open(pmsg->mtxt,O_WRONLY | O_CREAT | O_TRUNC,0666);
if(fd < 0){
fprintf(stderr,"Fail to open %s : %s\n",pmsg->mtxt,strerror(errno));
exit(EXIT_FAILURE);
}
if(ftruncate(fd,pmsg->size) < 0)
{
perror("Fail to ftruncate");
exit(EXIT_FAILURE);
}
while(1)
{
if(recv(sockfd,pmsg,sizeof(MSG),0) <= 0)
break;
if(pmsg->size == 0)
break;
write(fd,pmsg->mtxt,pmsg->size);
}
return ;
}
int do_get(int sockfd,MSG *pmsg)
{
int fd;
struct stat f_info;
fd = open(pmsg->mtxt,O_RDONLY);
if(fd < 0){
fprintf(stderr,"Fail to open %s : %s\n",pmsg->mtxt,strerror(errno));
pmsg->type = NEXIST_FILE;
}
if(fstat(fd,&f_info) < 0)
{
perror("Fail to fstat");
pmsg->type = NEXIST_FILE;
}
if(pmsg->type == NEXIST_FILE)
{
//告诉客户端结果
send(sockfd,pmsg,sizeof(MSG),0);
return -1;
}else{
pmsg->type = YEXIST_FILE;
pmsg->size = f_info.st_size;
send(sockfd,pmsg,sizeof(MSG),0);
}
while(1)
{
pmsg->size = read(fd,pmsg->mtxt,sizeof(pmsg->mtxt));
if(send(sockfd,pmsg,sizeof(MSG),0) < 0)
{
perror("Fail to send");
exit(EXIT_FAILURE);
}
if(pmsg->size == 0)
break;
}
return 0;
}
int do_list(int sockfd)
{
DIR *pdir;
MSG msg;
struct dirent *pdirent;
pdir = opendir(".");
if(pdir == NULL)
{
msg.type = NEXIST_FILE;
send(sockfd,&msg,sizeof(MSG),0);
return -1;
}
while ( pdirent = readdir(pdir) )
{
if(pdirent->d_name[0] == '.')
continue;
msg.type = YEXIST_FILE;
strcpy(msg.mtxt,pdirent->d_name);
if(send(sockfd,&msg,sizeof(MSG),0) < 0)
{
perror("Fail to send");
exit(EXIT_FAILURE);
}
}
msg.type = NEXIST_FILE;
if(send(sockfd,&msg,sizeof(MSG),0) < 0)
{
perror("Fail to send");
exit(EXIT_FAILURE);
}
return 0;
}
void do_client(int connect_fd)
{
MSG msg;
while(1)
{
if(recv(connect_fd,&msg,sizeof(MSG),0) <= 0)
{
perror("Fail to recv");
exit(EXIT_FAILURE);
}
switch(msg.type)
{
case PUT_FILE:
do_put(connect_fd,&msg);
break;
case GET_FILE:
do_get(connect_fd,&msg);
break;
case LIST_DIR:
do_list(connect_fd);
break;
}
}
exit(EXIT_SUCCESS);
}
int main(int argc, const char *argv[])
{
int listen_fd;
pid_t pid;
int connect_fd;
struct sockaddr_in server_addr;
struct sockaddr_in peer_addr;
socklen_t addrlen = sizeof(struct sockaddr_in);
if(argc < 3)
{
fprintf(stderr,"Usage : %s ip port\n",argv[0]);
exit(EXIT_FAILURE);
}
if(signal(SIGCHLD,handler_signal) == SIG_ERR)
{
perror("Fail to signal");
exit(EXIT_FAILURE);
}
listen_fd = socket(AF_INET,SOCK_STREAM,0);
if(listen_fd < 0){
perror("Fail to socket");
exit(EXIT_FAILURE);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(argv[2]));
server_addr.sin_addr.s_addr = inet_addr(argv[1]);
if(bind(listen_fd,(struct sockaddr *)&server_addr,sizeof(struct sockaddr_in)) < 0)
{
perror("Fail to bind");
exit(EXIT_FAILURE);
}
listen(listen_fd,128);
printf("listen ...\n");
while(1)
{
connect_fd = accept(listen_fd,(struct sockaddr *)&peer_addr,&addrlen);
if(connect_fd < 0){
perror("Fail to accept");
exit(EXIT_FAILURE);
}
printf("------------------------------------------------\n");
printf("connect_fd = %d\n",connect_fd);
printf("Port : %d\n",ntohs(peer_addr.sin_port));
printf("IP : %s\n",inet_ntoa(peer_addr.sin_addr));
printf("---------------------------------------------\n");
pid = fork();
if(pid < 0){
perror("Fail to fork");
exit(EXIT_FAILURE);
}
if(pid == 0)
{
close(listen_fd);
do_client(connect_fd);
}
//避免文件描述符号浪费
close(connect_fd);
}
return 0;
}
#include <head.h>
typedef struct
{
int type;
int size;
char mtxt[1024];
}MSG;
#define PUT_FILE 10
#define GET_FILE 20
#define LIST_DIR 30
#define NEXIST_FILE 40
#define YEXIST_FILE 50
int do_put(int sockfd,char *filename)
{
int fd;
MSG msg;
struct stat f_info;
fd = open(filename,O_RDONLY);
if(fd < 0){
fprintf(stderr,"Fail to open %s : %s\n",filename,strerror(errno));
return -1;
}
if(fstat(fd,&f_info) < 0)
{
perror("Fail to fstat");
return -1;
}
msg.type = PUT_FILE;
msg.size = f_info.st_size;
strcpy(msg.mtxt,filename);
if(send(sockfd,&msg,sizeof(MSG),0) < 0)
{
perror("Fail to send");
exit(EXIT_FAILURE);
}
while(1)
{
msg.size = read(fd,msg.mtxt,sizeof(msg.mtxt));
if(send(sockfd,&msg,sizeof(MSG),0) < 0)
{
perror("Fail to send");
exit(EXIT_FAILURE);
}
if(msg.size == 0)
break;
}
return 0;
}
int do_get(int sockfd,char *filename)
{
int fd;
MSG msg;
msg.type = GET_FILE;
strcpy(msg.mtxt,filename);
if(send(sockfd,&msg,sizeof(MSG),0) < 0)
{
perror("Fail to send");
exit(EXIT_FAILURE);
}
//等待服务器端结果:文件存放或不存在
if(recv(sockfd,&msg,sizeof(MSG),0) <= 0)
{
perror("Fail to send");
exit(EXIT_FAILURE);
}
if(msg.type == NEXIST_FILE)
{
printf("The get file:%s is not exist!\n",filename);
return -1;
}
fd = open(msg.mtxt,O_WRONLY | O_CREAT | O_TRUNC,0666);
if(fd < 0){
fprintf(stderr,"Fail to open %s : %s\n",msg.mtxt,strerror(errno));
exit(EXIT_FAILURE);
}
if(ftruncate(fd,msg.size) < 0)
{
perror("Fail to ftruncate");
exit(EXIT_FAILURE);
}
while(1)
{
if(recv(sockfd,&msg,sizeof(MSG),0) <= 0)
break;
if(msg.size == 0)
break;
write(fd,msg.mtxt,msg.size);
}
return 0;
}
int do_list(int sockfd)
{
MSG msg;
msg.type = LIST_DIR;
if(send(sockfd,&msg,sizeof(MSG),0) < 0)
{
perror("Fail to send");
exit(EXIT_FAILURE);
}
while(1)
{
if(recv(sockfd,&msg,sizeof(MSG),0) <= 0)
break;
if(msg.type == NEXIST_FILE)
break;
printf("%s\n",msg.mtxt);
}
return 0;
}
int do_task(int sockfd,char *pcmd,char *filename)
{
if(strncmp(pcmd,"get",3) == 0)
{
do_get(sockfd,filename);
}else if(strncmp(pcmd,"put",3) == 0){
do_put(sockfd,filename);
}else if(strncmp(pcmd,"list",4) == 0){
do_list(sockfd);
}else{
printf("Invalid cmd : %s\n",pcmd);
return -1;
}
return 0;
}
int main(int argc, const char *argv[])
{
char buf[1024];
int sockfd;
char *pcmd,*pname;
int connect_fd;
struct sockaddr_in server_addr;
if(argc < 3)
{
fprintf(stderr,"Usage : %s ip port\n",argv[0]);
exit(EXIT_FAILURE);
}
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd < 0){
perror("Fail to socket");
exit(EXIT_FAILURE);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(argv[2]));
server_addr.sin_addr.s_addr = inet_addr(argv[1]);
if(connect(sockfd,(struct sockaddr *)&server_addr,sizeof(struct sockaddr_in)) < 0)
{
perror("Fail to bind");
exit(EXIT_FAILURE);
}
while(1)
{
printf(">");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf) - 1] = '\0';
if(strncmp(buf,"quit",4) == 0)
break;
pcmd = strtok(buf," ");
pname = strtok(NULL," ");
do_task(sockfd,pcmd,pname);
}
return 0;
}
O(∩_∩)O~于君共勉
基于TCP的TFTP(Trivial File Transfer Protocol,简单文件传输协议) 的c编程实现
原文地址:http://blog.csdn.net/u011401496/article/details/38777051