通过写如下的ftp远程服务器的小项目来巩固自己对Linux系统编程的学习。若有不足之处欢迎大家指正。
功能说明
ls——列出远程服务端当前目录下的所有文件
cd——加远程服务端文件夹名以进入该文件夹
pwd——显示程服务端当前路径
get——加文件名来获取服务端文件
put——加文件名把该文件拷贝给远程服务端一份
lls——查看客户端当前路径下的文件
lcd——加客户端文件夹名以进入该文件夹
quit——客户端退出
服务端代码:
#include <stdbool.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
//#include <linux/in.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define LS 1
#define GET 2
#define PWD 3
#define LCD 4
#define LLS 5
#define CD 6
#define PUT 7
#define QUIT 8
struct Msg
{ int if_exist; //传递判断文件是否存在信息
char cmd[1024]; //存储指令
char date[1024]; //存储服务端往客户端发的数据
char date2[1024]; //存储客户端往服务端发的数据
};
//解析指令,以便选择结构使用
int ChangeCmd(char *Cmd)
{
if(!strcmp(Cmd,"ls")) return LS;
if(!strcmp(Cmd,"quit")) return QUIT;
if(!strcmp(Cmd,"pwd")) return PWD;
if(strstr(Cmd,"cd")!=NULL) return CD;
if(strstr(Cmd,"get")!=NULL) return GET;
if(strstr(Cmd,"put")!=NULL) return PUT;
return -1;
}
//获取指令中的文件名
char *GetName(char *name)
{
char *n;
n=strtok(name," ");
n=strtok(NULL," ");
return n;
}
//消息处理
void Msg_Handler(struct Msg msg,int c_fd,int mark)
{
char *file=NULL;
int fd;
char Buf[1024]={0};
FILE *r;
char *name;
printf("cmd: %s\n",msg.cmd);
int sum=ChangeCmd(msg.cmd);
switch(sum){
case LS:
case PWD:
r=popen(msg.cmd,"r");
fread(msg.date,sizeof(msg.date),1,r);
write(c_fd,&msg,sizeof(msg));
break;
case CD:
name=GetName(msg.cmd);
printf("dir:%s",name);
chdir(name);
break;
case GET:
file=GetName(msg.cmd);
if(access(file,F_OK)==-1){
strcpy(msg.date,"No This File");
msg.if_exist=0;
write(c_fd,&msg,sizeof(msg));
}else{
msg.if_exist=1;
fd=open(file,O_RDWR);
read(fd,Buf,sizeof(Buf));
close(fd);
strcpy(msg.date,Buf);
write(c_fd,&msg,sizeof(msg));
}
break;
case PUT:
fd=open(GetName(msg.cmd),O_RDWR|O_CREAT,0600);
write(fd,msg.date2,strlen(msg.date2));
close(fd);
break;
case QUIT:
printf("%d client quit!\n",mark);
exit(0);
}
}
int main(int argc,char **argv)
{
int s_fd;
int c_fd;
int n_read;
int mark=0;
char readbuf[128]={0};
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
struct Msg msg;
memset(&s_addr,0,sizeof(struct sockaddr_in));
memset(&c_addr,0,sizeof(struct sockaddr_in));
//1.socket
s_fd=socket(AF_INET,SOCK_STREAM,0);
if(s_fd==-1){
perror("socket");
exit(-1);
}
s_addr.sin_family=AF_INET;
s_addr.sin_port=htons(atoi(argv[2]));
inet_aton(argv[1],&s_addr.sin_addr);
//2.binf
bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
//3.listen
listen(s_fd,10);
//4.accept
int clen=sizeof(struct sockaddr_in);
while(1){
c_fd=accept(s_fd,(struct sockaddr *)&c_addr,&clen);
if(c_fd==-1)
{
perror("accept");
}
mark++;
printf("get %d connect:%s\n",mark,inet_ntoa(c_addr.sin_addr));
if(fork()==0){
//5.read
memset(msg.date,0,sizeof(msg.date));
memset(readbuf,0,sizeof(readbuf));
sprintf(readbuf,"welcom No.%d client",mark);
write(c_fd,readbuf,sizeof(readbuf));
while(1){
memset(msg.cmd,0,sizeof(msg.cmd));
n_read=read(c_fd,&msg,sizeof(msg));
if(n_read==-1){
perror("read");
}else{
Msg_Handler(msg,c_fd,mark);
}
}
break;
}
}
return 0;
}
客户端代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdbool.h>
#include <sys/socket.h>
//#include <linux/in.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#define LS 1
#define GET 2
#define PWD 3
#define LCD 4
#define LLS 5
#define CD 6
#define PUT 7
#define QUIT 8
struct Msg
{ int if_exist;
char cmd[1024];
char date[1024];
char date2[1024];
};
int ChangeCmd(char *Cmd)
{
if(strstr(Cmd,"lcd")!=NULL) return LCD;
if(!strcmp(Cmd,"lls")) return LLS;
if(!strcmp(Cmd,"ls")) return LS;
if(!strcmp(Cmd,"quit")) return QUIT;
if(!strcmp(Cmd,"pwd")) return PWD;
if(strstr(Cmd,"cd")!=NULL) return CD;
if(strstr(Cmd,"get")!=NULL) return GET;
if(strstr(Cmd,"put")!=NULL) return PUT;
return -1;
}
char *GetName(char *name)
{
char *n;
n=strtok(name," ");
n=strtok(NULL," ");
return n;
}
void DoFile(struct Msg msg,struct Msg Msg)
{
int new_fd;
if(Msg.if_exist==0){
printf("%s\n",Msg.date);
}else{
char *p=GetName(msg.cmd);
new_fd=open(p,O_RDWR|O_CREAT,0600);
write(new_fd,Msg.date,strlen(Msg.date));
close(new_fd);
}
}
void Cmd_Handler(struct Msg msg,int c_fd)
{
int ret;
char *dir;
int n_read;
char buf[108];
int fd;
struct Msg Msg;
ret= ChangeCmd(msg.cmd);
switch(ret){
case CD:
write(c_fd,&msg,sizeof(msg));
break;
case LS:
case PWD:
write(c_fd,&msg,sizeof(msg));
memset(msg.date,0,sizeof(msg.date));
n_read=read(c_fd,&msg,sizeof(msg));
printf("---------------------------\n");
printf("%s",msg.date);
printf("---------------------------\n");
break;
case GET:
write(c_fd,&msg,sizeof(msg));
n_read=read(c_fd,&Msg,sizeof(Msg));
DoFile(msg,Msg);
break;
case PUT:
memset(&buf,0,sizeof(buf));
strcpy(buf,msg.cmd);
dir=GetName(buf);
if(access(dir,F_OK)==-1){
printf("No This File\n");
}else{
fd=open(dir,O_RDWR);
read(fd,msg.date2,sizeof(msg.date2));
close(fd);
write(c_fd,&msg,sizeof(msg));
}
break;
case LLS:
system("ls");
break;
case LCD:
dir=GetName(buf);
chdir(dir);
break;
case QUIT:
write(c_fd,&msg,sizeof(msg));
exit(-1);
}
}
int main(int argc,char** argv)
{
int c_fd;
int n_read;
struct Msg msg;
char readbuf[128]={0};
struct sockaddr_in c_addr;
memset(&c_addr,0,sizeof(struct sockaddr_in));
c_fd=socket(AF_INET,SOCK_STREAM,0);
if(c_fd==-1){
perror("socket");
exit(-1);
}
c_addr.sin_family=AF_INET;
c_addr.sin_port=htons(atoi(argv[2]));
inet_aton(argv[1],&c_addr.sin_addr);
if(connect(c_fd,(struct sockaddr*)&c_addr,sizeof(struct sockaddr))==-1){
perror("connect");
exit(-1);
}
memset(msg.date,0,sizeof(msg.date));
memset(msg.date2,0,sizeof(msg.date2));
n_read=read(c_fd,readbuf,sizeof(readbuf));
printf("%s\n",readbuf);
while(1){
memset(msg.cmd,0,sizeof(msg.cmd));
gets(msg.cmd);
Cmd_Handler(msg,c_fd);
}
return 0;
}
运行结果:
以下贴出一部分运行的结果,具体功能实现还需亲自实验来感受