tftp--实现服务器与客户端的下载与上传


项目功能:实现服务器与客户端的下载与上传,及linux系统下的tftp功能

项目名称:tftp--实现服务器与客户端的下载与上传

开发环境:linux /C

开发工具:GCC/GDB 

网络协议:TCP/IP


补充说明:程序中默认server端有upload文件夹用以接收client端上传的数据,client端有download文件夹用以下载server端的文件

开发流程:


编译流程:

1.cc    server.c  -o server

2.cc  client.c  -o client


运行l流程:

1.  ./server  192.168.1.207(server ip)  8888(port)

 2. ./client    192.168.1.207  8888  

调试效果:

client 端


server 端



1.server.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<signal.h>
#include<errno.h>
   #include <dirent.h>


typedef struct { 
	char cmd[10];
	int size;
	char buf[1024];
}MSG;
MSG msg;
enum{list,get,put};
int 	do_list(int connect_fd)
{
	
	char buf[1024];
	int n;
	int fd;
	DIR *pdir;
	struct dirent *pdirent;
	if((pdir = opendir(".")) == NULL)
	{
		perror("Fail to open directory ");
		exit(EXIT_FAILURE);
	}
	while((pdirent = readdir(pdir)) != NULL)
	{
		if(pdirent->d_name[0] == '.' )
			continue;
		strcpy(msg.buf,pdirent->d_name);
		msg.size = strlen(msg.buf);
		msg.size = send(connect_fd,&msg,sizeof(MSG),0);
	}
	msg.size = 0;
	send(connect_fd,&msg,sizeof(MSG),0);
	puts("send list successfully");	
	return 0;
}
			

int do_get(int connect_fd)
{
	char filename[10];
	int n;
	int fd;
	struct stat fileinfo;
	if(recv(connect_fd,&msg,sizeof(MSG),0) < 0)
	{
		perror("fail to recv");
		exit(EXIT_FAILURE);	
	}

	if(stat(msg.buf,&fileinfo) < 0)
	{
		perror("fail to stat");
		msg.size = -1;
		strcpy(msg.buf,strerror(errno));
		send(connect_fd,&msg,sizeof(MSG),0);
		return -1;
	}
	msg.size = fileinfo.st_size;
	strcpy(filename,msg.buf);


	puts("***********************");
	printf("send file size : %d\n",msg.size);
	printf("send filename : %s\n",msg.buf);
	puts("***********************");

	if(send(connect_fd,&msg,sizeof(MSG),0) < 0)
	{
		perror("fail to recv");
		exit(EXIT_FAILURE);	
	}

	if((fd = open(msg.buf,O_RDONLY)) < 0)
	{
		fprintf(stderr,"Fail to open %s, %s\n",msg.buf,strerror(errno));
		exit(EXIT_FAILURE);
	}

	while(1)
	{
		msg.size = read(fd, msg.buf,sizeof(msg.buf));
		 send(connect_fd,&msg,sizeof(MSG),0);
		if(msg.size == 0)
			break;
	}
	printf("send file %s successfully\n",filename);
	
	return 0;
}
int do_put(int connect_fd)
{
	char buf[1024];
	int n;
	int fd;
	if(recv(connect_fd,&msg,sizeof(msg),0) <= 0)
	{
		perror("fail to recv");
		exit(EXIT_FAILURE);
	}

	puts("**********************************");
	printf("upload filename  : %s\n",msg.buf);
	printf("size:   %d\n",msg.size);
	puts("**********************************");

	strcpy(buf,"./upload/");
	strcat(buf,msg.buf);
	if((fd = open(buf,O_WRONLY | O_CREAT | O_TRUNC,0666)) < 0)
	{
		perror("Fail to accept");
		exit(EXIT_FAILURE);
	}
	ftruncate(fd,msg.size);

	while(1)
	{
		 recv(connect_fd,&msg,sizeof(MSG),0);
		write(fd,msg.buf,msg.size);
		if(msg.size == 0)
			break;
	}
	printf("send file successfully!\n");
	
	exit(EXIT_SUCCESS);
	
}
int  getcmd(char *pcmd)
{
	if(strcmp(pcmd,"list") == 0)
		return 0;
	if(strcmp(pcmd,"get") == 0)
		return 1;
	if(strcmp(pcmd,"put") == 0)
		return 2;
}
void	do_task(int connect_fd,char *cmd)
{
	MSG msg;

	switch(getcmd(cmd))
	{
		case put:
			printf("recv file  from client...\n");
			do_put(connect_fd);
			break;
		case get:
			printf("send file to  client...\n");
			do_get(connect_fd);
			break;
	case list:
			printf("send file list to client...\n");
			do_list(connect_fd);
			break;
		default :
			break;
	}

	return;
}
int do_client(int connect_fd)
{
	MSG msg;
	int n;
	while(1)
	{
		if((n =recv(connect_fd,&msg,sizeof(msg),0) )< 0)
		{
			perror("fail to recv");
			exit(EXIT_FAILURE);
		}
		if(n == 0)
			break;

		do_task(connect_fd,msg.cmd);

	}

	exit(EXIT_FAILURE);
}	
void signal_handler(int signum)	
{
	waitpid(-1,NULL,WNOHANG);
	return;
}
int main(int argc, const char *argv[])
{
	pid_t pid;
	int listen_fd;
	int connect_fd;
	socklen_t addrlen;
	struct sockaddr_in peer_addr;
	struct sockaddr_in server_addr;
	if(argc < 0)
	{
		perror("fail to argc");
		exit(EXIT_FAILURE);
		
	}
	if(signal(SIGCHLD,signal_handler) == SIG_ERR)
	{
		perror("fail to signal");
		exit(EXIT_FAILURE);
	}
	if((listen_fd = socket(AF_INET,SOCK_STREAM,0) )< 0)
	{
		perror("fail to socket");
		exit(EXIT_FAILURE);
	}
	memset(&server_addr,0,sizeof(server_addr));
	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(server_addr)) < 0) //描述本机端口和IP,要知道数据包发往哪个进程
	{
		perror("Fail to bind");
		exit(EXIT_FAILURE);
	}

	if(listen(listen_fd,8 ) < 0)//监听连接的套接字,接收各客户端的请求,返回监听套接字文件描述符
	{
		perror("Fail to listen");
		exit(EXIT_FAILURE);
	}
	puts("listening ...");
	addrlen = sizeof(peer_addr);  
	while(1)
	{
		if((connect_fd = accept(listen_fd,(struct sockaddr *)&peer_addr,&addrlen)) < 0)
		{
			perror("Fail to accept");//提取客户发过来的请求,返回新的已连接的套接字文件描述符
			exit(EXIT_FAILURE);
		}
		puts("*************************");
		printf("IP : %s\n",inet_ntoa(peer_addr.sin_addr));
		printf("PORT : %d\n",ntohs(peer_addr.sin_port));
		puts("*************************");
		if((pid = fork()) < 0)  
		{
			perror("Fail to listen");
			exit(EXIT_FAILURE);
		}
		if(pid == 0)
		{
			do_client(connect_fd);
		}
		close(connect_fd);
	}
	exit(EXIT_FAILURE);
}	



2.client.c


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

typedef struct {
	char cmd[10];
	int size;
	char buf[1024];
}MSG;

enum{list,get,put};
int do_list(client_fd,pname)
{
	MSG msg;
	int fd;
	while(1)
	{
		recv(client_fd,&msg,sizeof(MSG),0);
		if(msg.size == 0)
			break;
		printf("%s\n",msg.buf);
	}
	puts("get list successfully");	
	return 0;
}


int	do_get(int client_fd,char *filename)
{
	MSG msg;
	int fd;
	char buf[1024];
	strcpy(msg.buf,filename);

	if(send (client_fd,&msg,sizeof(MSG),0) < 0)
	{
		perror("Fail to send");
		exit(EXIT_FAILURE);
	}

	recv(client_fd,&msg,sizeof(MSG),0);
    if(msg.size < 0)	
	{
		printf("Error :%s  \n",msg.buf);
		return -1;
	}

	puts("***********************");
	printf(" download file size : %d\n",msg.size);
	printf(" download filename : %s\n",msg.buf);
	puts("***********************");
	
	strcpy(buf,"./download/");
	strcat(buf,msg.buf);
	if((fd = open(buf,O_WRONLY | O_CREAT | O_TRUNC,0666)) < 0)
	{
		fprintf(stderr,"Fail to open %s,%s\n",buf,strerror(errno));
		exit(EXIT_FAILURE);
	}

	ftruncate(fd, msg.size);

	while(1)
	{
		recv(client_fd,&msg,sizeof(MSG),0);
		if(msg.size == 0)
			break;
		write(fd,msg.buf,msg.size);
	} 
	printf("download file %s successfully\n",filename);
	return 0;
}
int do_put(int client_fd,char *filename)
{
	MSG msg;
	int fd;
	int n;
		if((fd = open(filename,O_RDONLY)) < 0)
		{
			perror("Fail to open");
			exit(EXIT_FAILURE);
			
		}
		msg.size  = lseek(fd,0,SEEK_END);
		strcpy(msg.buf,filename);
		lseek(fd,0,SEEK_SET);

		puts("**********************************");
		printf("filename : %s\n",msg.buf);
		printf("size :%d\n",msg.size);
		puts("**********************************");

		if(send(client_fd,&msg,sizeof(MSG),0) < 0)
		{
			perror("Fail to send");
			exit(EXIT_FAILURE);
		}
		while(1)
		{

			msg.size = read(fd,msg.buf,sizeof(msg.buf));
			if(send(client_fd,&msg,sizeof(MSG),0) < 0)
			{
				perror("Fail to read");
				exit(EXIT_FAILURE);
			}	
			if(msg.size == 0)
				break;
		}
		printf("upload file successfully!\n");

	return 0; 
}
int  getcmd(char *pcmd)
{
	if(strcmp(pcmd,"list") == 0)
		return 0;
	if(strcmp(pcmd,"get") == 0)
		return 1;
	if(strcmp(pcmd,"put") == 0)
		return 2;
}
int	do_task(char *pcmd,char *pname,int client_fd)
{
	MSG msg;
	char buf[1024];
	int fd;
	switch(getcmd(pcmd))
	{
	case list:
		printf("get file list from the server ...\n");
		strcpy(msg.cmd,pcmd);
		
		if(send(client_fd,&msg,sizeof(MSG),0) < 0)
		{
			perror("FAIL to send");
			exit(EXIT_FAILURE);
		}
		do_list(client_fd,pname);
					break;
	case get:
		printf("file  %s is downloading from server ...\n",pname);
		strcpy(msg.cmd , pcmd);
		if(send(client_fd,&msg,sizeof(MSG),0) < 0)
		{
			perror("FAIL to send");
			exit(EXIT_FAILURE);
		}
		do_get(client_fd,pname);
		break;
	case put:
		printf(" file  %s is uploading to server ...\n",pname);
		strcpy(msg.cmd,pcmd);
		if(send(client_fd,&msg,sizeof(MSG),0) < 0)
		{
			perror("Fail to send!");
			exit(EXIT_FAILURE);
		}
		do_put(client_fd,pname);
		break;

	default:
		break;

	}
	return 0;

}
int main(int argc, const char *argv[])
{
	MSG msg;
	char buf[1024];
		char *pname,*pcmd;
	int client_fd;
	pid_t  pid;
	int connect_fd;
	socklen_t addrlen;
	struct sockaddr_in server_addr;
	
	if((client_fd = socket(AF_INET,SOCK_STREAM,0) )< 0)
	{
		perror("fail to socket");
		exit(EXIT_FAILURE);
	}
	memset(&server_addr,0,sizeof(server_addr));
	
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr =inet_addr(argv[1]);
	server_addr.sin_port = htons(atoi(argv[2]));


	if(connect(client_fd,(struct sockaddr *)&server_addr,sizeof(server_addr)) < 0)	
	{
		perror("Fail to accept");
		exit(EXIT_FAILURE);
	}
	
		while(1)
		{
			printf("tftp>");
			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(pcmd,pname,client_fd);
		}
		exit(EXIT_FAILURE);
	
	

	
	return 0;
}


  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值