Linux 小项目(1)---简易FTP服务器

本文介绍了如何使用C语言在Linux系统上编写一个简单的FTP服务器,该服务器支持多个客户端连接,实现文件的上传、下载、查看目录等功能。通过fork函数创建子进程处理客户端请求,使用popen执行shell命令来实现文件操作和路径显示。同时,给出了服务器端和客户端的代码示例,展示了如何交互执行各种指令。最后,提供了客户端和服务器端的运行示例,展示了一个基本的FTP文件传输流程。
摘要由CSDN通过智能技术生成

一、FTP服务器

本小节我们通过C语言在Linux系统上编写简易FTP服务器代码。

什么是FTP服务器?
FTP服务器(File Transfer Protocol Server)是在互联网上提供文件存储和访问服务的计算机,它们依照FTP协议提供服务。 FTP是File Transfer Protocol(文件传输协议)。顾名思义,就是专门用来传输文件的协议。简单地说,支持FTP协议的服务器就是FTP服务器。

所设计的简易FTP服务器代码包含服务器端server.c和客户端client.c。服务器通过fork函数生成多个进程方式连接多个客户端。客户端也通过fork函数同时进行接收数据处理和发送数据处理。

通过客户端输入指令实现以下功能:
1、获取服务器的文件:scp XXX (XXX表示文件名,可包含路径)
2、上传文件到服务器:load XXX(XXX表示文件名,可包含路径)
3、显示服务器当前文件夹路径:spwd
4、显示客户端当前文件夹路径:lpwd
5、显示服务器中任意路径的文件:sls 路径名 (当路径为空时,显示当前路径的文件)
6、显示客户端中任意路径的文件:lls 路径名 (当路径为空时,显示当前路径的文件)
7、客户端退出:quit

spwd、lpwd、sls、lls指令都是通过popen函数来执行shell命令。
scp、load指令原理相同,先是打开并读取文件,向接收文件端发送数据包头(本项目是字符串”file startxxx”,xxx为文件名),再发文件内容,最后发数据包尾(本项目是字符串”file exit”)。
具体实现原理不详细阐述,可看代码细细体会。

二、项目代码

1、服务器端

//文件server.c
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc,char* argv[])
{
        if(argc!=3)
        {
                printf("arg error!\n");
                exit(-1);
        }
        int sockfd,c_fd;
        struct sockaddr_in s_addr,c_addr;
        socklen_t c_size;
        pid_t pid1;
        char* c_ip;
        char read_buf[1024]="";
        char write_buf[1024]="";
        int read_size=0;
        int write_size=0;
        memset(&s_addr,0,sizeof(struct sockaddr_in));
        memset(&c_addr,0,sizeof(struct sockaddr_in));
        s_addr.sin_family=AF_INET;
        s_addr.sin_port=htons(atoi(argv[2]));
        inet_aton(argv[1],&(s_addr.sin_addr));
        sockfd=socket(AF_INET,SOCK_STREAM,0);
        if(sockfd==-1)
        {
                printf("socket create fail!\n");
        }
        if(bind(sockfd,(struct sockaddr*)&s_addr,sizeof(struct sockaddr_in))==-1)
        {
                printf("bind fail!\n");
                exit(-1);
        }
        else
        {
                printf("server:%s %d\n",argv[1],ntohs(s_addr.sin_port));
        }
        if(listen(sockfd,5)==-1)
        {
                printf("listen fail!\n");
        }
        c_size=sizeof(struct sockaddr_in);
        while(1)
        {
                if((c_fd=accept(sockfd,(struct sockaddr*)&c_addr,&c_size))==-1)
                {
                        printf("ip+port get error\n");
                        perror("why");
                        close(c_fd);
                }
                else
                {
                        c_ip=inet_ntoa(c_addr.sin_addr);
                        printf("connect from:%s %d\n",c_ip,ntohs(c_addr.sin_port));
                        if((pid1=fork())<0)
                        {
                                printf("fork fail!\n");
                                close(c_fd);
                        }
                        else if(pid1==0)
                        {
								FILE* fp;
								int fd1;
                                char ret[1024];
								int nread;
								char* str_loop;
								char* str_info=malloc(1024);
								int file_size;
								int count;
								char* file_loop;
								int file_flag=0;
								int n_write;
								char *char_p;
								int this_index=0;
								int index=0;	
                                while(1)
                                {
                                        memset(read_buf,'\0',1024);
                                        if((read_size=read(c_fd,read_buf,1024))==-1)
                                        {
												printf("read error!\n");
                                        }
                                        strncpy(read_buf,read_buf,read_size);
										if(strcmp(read_buf,"file exit")==0)
										{
												file_flag=0;
												close(fd1);
												printf("file load finish!\n");
										}
										 else if(file_flag==1)
										 {
												n_write=write(fd1,read_buf,read_size);
												if(n_write==-1)
												{
														printf("write fail!\n");
														perror("why");
												}
										 }
										 else if((file_loop=strstr(read_buf,"file start"))!=NULL)
										 {
												 file_flag=1;
												 file_loop+=strlen("file start");
												 printf("loading file:%s\n",file_loop);
												 char_p=file_loop;
												 this_index=0;
												 index=0;
												 while(1)
												 {
														if(*char_p== '\0')
																break;
														else if(*char_p=='/')
																this_index=index+1;
														index++;
														char_p++;
												 }
												 char_p=file_loop;
												 while(1)
												 {
														if(*(char_p+this_index)=='\0')
														{
																*char_p='\0';
																break;
														}
														*char_p=*(char_p+this_index);
														char_p++;
												 }
												 fd1=open(file_loop,O_RDWR|O_CREAT|O_TRUNC,0600);
										 }
										 else
										 {
												 //printf("%s\n",read_buf);
										 }
										if((str_loop=strstr(read_buf,"sls"))!=NULL)
										{
												str_loop+=3;
												memset(ret,'\0',1024);
												if(read_size!=3)
												{
														sprintf(str_info,"ls %s",str_loop);
														fp=popen(str_info,"r");
												}
												else
												{
														fp=popen("ls","r");
												}
												nread=fread(ret,1,1024,fp);
												strncpy(ret,ret,nread);
												if(write(c_fd,ret,strlen(ret))==-1)
												{
														printf("write error!\n");
												}
												pclose(fp);				
										}
                                        if(strcmp(read_buf,"spwd")==0)
                                        {
                                                memset(ret,'\0',1024);
                                                fp=popen("pwd","r");
                                                nread=fread(ret,1,1024,fp);
                                                strncpy(ret,ret,nread);
                                                if(write(c_fd,ret,strlen(ret))==-1)
                                                {
                                                        printf("write error!\n");
                                                }
                                                pclose(fp);
                                        }
                                        if((str_loop=strstr(read_buf,"scp"))!=NULL)
                                        {
												str_loop+=3;
												printf("finding file:%s\n",str_loop);
                                                memset(ret,'\0',1024);
                                                fp=popen("ls","r");
                                                nread=fread(ret,1,1024,fp);
                                                strncpy(ret,ret,nread);
                                                pclose(fp);
												memset(ret,'\0',1024);
												fd1=open(str_loop,O_RDWR);
												if(fd1==-1)
												{
														printf("dont find file!\n");
														if(write(c_fd,"fail",strlen("fail"))==-1)
														{
															   printf("write error!\n");
														}
												}
												else
												{
														file_size=lseek(fd1,0,SEEK_END);
														lseek(fd1,0,SEEK_SET);
														count=(file_size/1023)+1;
														nread=0;
														memset(str_info,'\0',1024);
														sprintf(str_info,"file start%s",str_loop);
														if(write(c_fd,str_info,strlen(str_info))==-1)
														{
																printf("write error!\n");
														}
														usleep(100000);
														while(count--)
														{
																memset(ret,'\0',1024);
																nread=read(fd1,ret,1023);
																if(nread==-1)
																		printf("read fail!\n");
																else
																{
																		strncpy(ret,ret,nread);                         
																		if(write(c_fd,ret,strlen(ret))==-1)
																		{
																				printf("write error!\n");
																		}
																}
														}
														usleep(100000);
														if(write(c_fd,"file exit",strlen("file exit"))==-1)
														{
																printf("write error!\n");
														}
														printf("file load finish!\n");
												}
												close(fd1);
										}
										if(strcmp(read_buf,"fail")==0)
										{
												printf("file load fail!\n");
										}
                                        if(strcmp(read_buf,"quit")==0)
                                        {
                                                printf("client quit!\n");
												if(write(c_fd,"quit",strlen("quit"))==-1)
												{
													printf("write error!\n");
												}
                                                close(c_fd);
                                                exit(0);
                                        }
                                }
                        }
                }
        }
        close(sockfd);
        return 0;
}

2、客户端

//文件client.c
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>  
#include <string.h> 
int main(int argc,char* argv[])
{
        pid_t pid;
        if(argc!=3) 
        {
                printf("arg error!\n"); 
                exit(-1);
        }
        int client_fd;
        int read_size=0;
        int write_size=0;
        struct sockaddr_in client_addr;
        char write_buf[1024];
        char read_buf[1024];
        memset(&client_addr,0,sizeof(struct sockaddr_in));
        client_fd=socket(AF_INET,SOCK_STREAM,0);
        client_addr.sin_family=AF_INET;
        client_addr.sin_port=htons(atoi(argv[2]));
        inet_aton(argv[1],&(client_addr.sin_addr));
        int flag=connect(client_fd,(struct sockaddr*)&client_addr,sizeof(struct sockaddr));
        if(flag==-1)
        {
                printf("connect fail!\n");
                exit(-1);
        }
        printf("connect:%s %s success!\n",argv[1],argv[2]);
        if((pid=fork())==-1)
        {
                printf("fork fail!\n");
        }
        else if(pid>0)
        {
				FILE* fp;
				char *char_p;
                int fd1;
				char ret[1024];
                int nread;
                char* str_loop;
                char* str_info=malloc(1024);
                int file_size;
                int count;
                while(1)
                {
					memset(write_buf,'\0',1024);
					char_p=write_buf;
					while(1)
					{
						scanf("%c",char_p);
						if(*char_p=='\n')
						{
							*char_p='\0';
							break;
						}
						else if(*char_p==' ')
							continue;
						else
							char_p++;
					}
					if((str_loop=strstr(write_buf,"load"))!=NULL)
					{
						str_loop+=4;
						printf("finding file:%s\n",str_loop);
						fd1=open(str_loop,O_RDWR);
						if(fd1==-1)
						{
							if(write(client_fd,"fail",strlen("fail"))==-1)
							{
								   printf("write error!\n");
							}
							printf("dont find file!\n");
						}
						else
						{
							file_size=lseek(fd1,0,SEEK_END);
							lseek(fd1,0,SEEK_SET);
							count=(file_size/1023)+1;
							nread=0;
							memset(str_info,'\0',1024);
							sprintf(str_info,"file start%s",str_loop);
							if(write(client_fd,str_info,strlen(str_info))==-1)
							{
									printf("write error!\n");
							}
							usleep(100000);
							while(count--)
							{
									memset(ret,'\0',1024);
									nread=read(fd1,ret,1023);
									if(nread==-1)
											printf("read fail!\n");
									else
									{
											strncpy(ret,ret,nread);
											if(write(client_fd,ret,strlen(ret))==-1)
											{
													printf("write error!\n");
											}
									}
							}
							usleep(100000);
							if(write(client_fd,"file exit",strlen("file exit"))==-1)
							{
									printf("write error!\n");
							}
							printf("file load finish!\n");
							close(fd1);
                        	}
					}
					else  if((str_loop=strstr(write_buf,"lls"))!=NULL)
					{
							str_loop+=3;
							memset(ret,'\0',1024);
							if(strlen(write_buf)!=2)
							{
									sprintf(str_info,"ls %s",str_loop);
									fp=popen(str_info,"r");
							}
							else
							{
									fp=popen("ls","r");
							}
							nread=fread(ret,1,1024,fp);
							strncpy(ret,ret,nread);
							printf("%s",ret);
							pclose(fp);
					}
					else if(strcmp(write_buf,"lpwd")==0)
					{
							memset(ret,'\0',1024);
							fp=popen("pwd","r");
							nread=fread(ret,1,1024,fp);
							strncpy(ret,ret,nread);
							printf("%s",ret);
							pclose(fp);
					}
					else
					{
							if(!((strstr(write_buf,"scp")!=NULL)||(strstr(write_buf,"sls")!=NULL)||(strstr(write_buf,"spwd")!=NULL)||(strstr(write_buf,"quit")!=NULL)))
									printf("this command dont exist!\n");
							else
							{
								if(write(client_fd,write_buf,strlen(write_buf))==-1)
								{
										printf("write error!\n");
								}
							}
					}
					if(strcmp(write_buf,"quit")==0)
					{
							//printf("write quit!\n");
							break;
					}
			}
        }
        else
        {
				char* file_loop;
                int file_flag=0;
                int fd1;
				int n_write;
				char *char_p;
				int this_index=0;
                int index=0;
                while(1)
                {
                         memset(read_buf,'\0',1024);
                         if((read_size=read(client_fd,read_buf,1024))==-1)
                         {
                                printf("read quit!\n");
                         }
                         strncpy(read_buf,read_buf,read_size);
						 if(strcmp(read_buf,"file exit")==0)
                         {
                                file_flag=0;
                                close(fd1);
                                printf("file load finish!\n");
                         }
						 else if(file_flag==1)
						 {
								n_write=write(fd1,read_buf,read_size);
								if(n_write==-1)
								{
									printf("write fail!\n");
									perror("why");
								}		
						 }
						 else if((file_loop=strstr(read_buf,"file start"))!=NULL)
						 {
							 file_flag=1;
							 file_loop+=strlen("file start");
							 printf("loading file:%s\n",file_loop);
							 char_p=file_loop;
							 this_index=0;
							 index=0;
							 while(1)
							 {
								if(*char_p== '\0')
									break;
								else if(*char_p=='/')
									this_index=index+1;
								index++;
								char_p++;
							 }
							 char_p=file_loop;
							 while(1)
							 {
								if(*(char_p+this_index)=='\0')
								{
									*char_p='\0';
									break;
								}
								*char_p=*(char_p+this_index);
								char_p++;
							 }
							 fd1=open(file_loop,O_RDWR|O_CREAT|O_TRUNC,0600);
						 }
						 else if(strcmp(read_buf,"fail")==0)
                         {
                                printf("file load fail!\n");
                         }
                         else if(strcmp(read_buf,"quit")==0)
                         {
                                //printf("read quit!\n");
                                break;
                         }
						 else
						 {
							printf("%s",read_buf);
						 }
                }
        }
        close(client_fd);
        return 0;
}

三、运行代码

1、客户端

sh@ubuntu:~/Desktop/client$ ./client 192.168.31.219 8888  //运行client IP 端口号
connect:192.168.31.219 8888 success!
lls  //显示客户端当前文件夹的文件
client
client.c
page2.txt
lpwd  //显示客户端当前路径
/home/sh/Desktop/client
sls  //显示服务器当前文件夹的文件
page1.txt
server
server.c
spwd  //显示服务器当前路径
/home/sh/Desktop/ftp
scp page1.txt  //获取服务器page1.txt文件
loading file:page1.txt
file load finish!
load page2.txt  //上传客户端page2.txt文件
finding file:page2.txt
file load finish!
scp /home/sh/Desktop/page3.txt  //获取服务器/home/sh/Desktop路径的page3.txt文件
loading file:/home/sh/Desktop/page3.txt
file load finish!
quit  //客户端退出

2、服务器端

sh@ubuntu:~/Desktop/ftp$ ./server 192.168.31.219 8888  //运行server IP 端口号
server:192.168.31.219 8888
connect from:192.168.31.219 47854
finding file:page1.txt  //查找文件
file load finish!
loading file:page2.txt  //接收文件
file load finish!
finding file:/home/sh/Desktop/page3.txt  //查找文件
file load finish!
client quit!  //客户端退出

四、总结

本节所设计的FTP服务器与系统自带的FTP服务器相比,比较简单。小伙伴们还可以自行添加功能,比如用户密码机制等,还可以试试用交叉编译生成执行文件在树莓派运行,实现不同平台之间的文件传输。

  • 2
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一盆电子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值