一、项目功能
ls:显示服务端文件列表
lls:显示客户端文件列表
cd:回到服务端上级目录
lcd:回到客户端上级目录
pwd:在服务端下显示显示服务端的路径,在客户端下显示客户端的路径
put:将客户端的文件上载到服务端
get:将服务端文件下载到客户端
quit:退出
二、服务端项目代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define LS 0
#define PWD 1
#define GET 2
#define CD 3
#define IFGO 4
#define LLS 5
#define LCD 6
#define PUT 7
#define QUIT 8
#define DOFILE 9
struct msg
{
int type;
char cmd[1024]; //存放命令和文件数据
char secondBuf[1024]; //存放文件内容
};
int get_cmd_type(char* cmd)//把字符串转成整型数
{
//int strcmp(const char *s1, const char *s2);//字符串比较
if(strcmp("ls",cmd) == 0) return LS;
if(strcmp("quit",cmd) == 0) return QUIT;
if(strcmp("pwd",cmd) == 0) return PWD;
//char *strstr(const char *haystack, const char *needle);//搜索一个字符串在另一个字符串中的第一次出现
if(strstr(cmd,"cd") != NULL) return CD;
if(strstr(cmd,"get") != NULL) return GET;
if(strstr(cmd,"put") != NULL) return PUT;
return 250;
}
char* get_dir(char* cmd)//分割字符串
{
char* fp;
//char *strtok(char *s, char *delim)//分解字符串 str 为一组字符串,delim 为分隔符,返回值:分隔符匹配到的第一个子串
fp=strtok(cmd,"|");
fp=strtok(NULL,"|");
return fp;
}
void msgs_Handler(struct msg msgs,int cfd)
{
int ret;
char* filename=NULL;
int fdfile;
FILE* fp=NULL;
char* dir=NULL;
char dataBuf[1024]={"\0"};
ret=get_cmd_type(msgs.cmd);//把字符串转成整型数
printf("cmd:%s\n",msgs.cmd);//打印客户端输出的指令
printf("ret:%d\n",ret);
switch(ret)
{
case PWD:
case LS:
//FILE *popen(const char *command, const char *type);
fp=popen(msgs.cmd,"r");
fread(msgs.cmd,sizeof(msgs.cmd),1,fp);
write(cfd,&msgs,sizeof(msgs));
break;
case CD:
dir=get_dir(msgs.cmd);//通过该函数获取文件名字
printf("dir:%s\n",dir);
//int chdir(const char *path)//改变当前工作目录
chdir(dir);//dir目录,ch,change,改变
break;
case GET:
filename=get_dir(msgs.cmd);//获取要操作的文件名(即指令后面的文件名字)
//int access(const char* pathname, int mode);//F_OK 值为0,判断文件是否存在
if(access(filename,F_OK) == -1)//判断该文件是否存在
{
strcpy(msgs.cmd,"No this file!");
write(cfd,&msgs,sizeof(msgs));
}
else
{
// msgs.type = DOFILE;
fdfile=open(filename,O_RDWR);//存在文件就打开文件
read(fdfile,dataBuf,sizeof(dataBuf));//读取信息
close(fdfile);//关闭文件
strcpy(msgs.cmd,dataBuf);//将读取的内容复制到cmd数组
write(cfd,&msgs,sizeof(msgs));//将读取的内容发送到客户端
//close(fdfile);//关闭文件
}
break;
case PUT:
filename=get_dir(msgs.cmd);//获取文件名称
fdfile=open(filename,O_RDWR|O_CREAT,0666);//有就打开文件,没有就创建文件
write(fdfile,msgs.secondBuf,strlen(msgs.secondBuf));//写内容到目标文件
close(fdfile);
break;
case QUIT:
printf("client quit!\n");
exit(-1);
break;
}
}
int main(int argc,char** argv)
{
if(argc != 3)//判断传入参数是否有三个
{
printf("program error!\n");
exit(-1);
}
int sfd;
int cfd;
int nread;
struct msg msgs;
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
memset(&s_addr,0,sizeof(struct sockaddr_in));
memset(&c_addr,0,sizeof(struct sockaddr_in));
//1.socket//创建套接字
//int socket(int domain, int type, int protocol);
sfd=socket(AF_INET,SOCK_STREAM,0);
if(sfd == -1)//判断是否创建成功
{
perror("socket");
exit(-1);
}
//2.bind//绑定IP号及端口
//int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
s_addr.sin_family=AF_INET;//协议族
s_addr.sin_port=htons(atoi(argv[2]));//返回网络字节序的值
inet_aton(argv[1],&s_addr.sin_addr);//把字符串形式的IP转换为网络能识别的格式
int nbind=bind(sfd,(struct sockaddr*)&s_addr,sizeof(struct sockaddr_in));
if(nbind == -1)
{
perror("bind");
exit(-1);
}
//3.lieten 监听
// int listen(int sockfd, int backlog);
int nlisten=listen(sfd,10);
if(nlisten == -1)
{
perror("listen");
exit(-1);
}
//4.accept 连接
//int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);
int len=sizeof(struct sockaddr_in);
while(1){
cfd=accept(sfd,(struct sockaddr*)&c_addr,&len);
if(cfd == -1)
{
perror("accept");
exit(-1);
}
printf("connect success:%s\n",inet_ntoa(s_addr.sin_addr));//打印连接的地址
if(fork() == 0){//一个子进程负责一条连接通道
while(1){
//5.recv 接受数据
// ssize_t recv(int sockfd, void *buf, size_t len, int flags);//与read功能类似
//ssize_t read(int fd, void *buf, size_t count);
memset(&msgs.cmd,'\0',sizeof(msgs.cmd));
nread=read(cfd,&msgs,sizeof(msgs));
if(nread == 0){//没有读到数据
printf("client out!\n");
exit(-1);
}
else if(nread > 0)//读到可用数据
{
msgs_Handler(msgs,cfd);//处理接受的数据指令
}
}
}
}
return 0;
}
三、客户端项目代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <pthread.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define LS 0
#define PWD 1
#define GET 2
#define CD 3
#define IFGO 4
#define LLS 5
#define LCD 6
#define PUT 7
#define QUIT 8
#define DOFILE 9
struct msg
{
int type;
char cmd[1024]; //存放命令和文件数据
char secondBuf[1024]; //存放文件内容
};
int get_cmd_type(char* cmd)//把字符串转换成整形数
{
//char *strstr(const char *haystack, const char *needle);//搜索一个字符串在另一个字符串中的第一次出现
if(strcmp(cmd,"ls") == 0) return LS;
if(strcmp(cmd,"lls") == 0) return LLS;
if(strcmp(cmd,"pwd") == 0) return PWD;
if(strcmp(cmd,"quit") == 0) return QUIT;
//char *strstr(const char *haystack, const char *needle);//搜索一个字符串在另一个字符串中的第一次出现
if(strstr(cmd,"get") != NULL) return GET;
if(strstr(cmd,"put") != NULL) return PUT;
if(strstr(cmd,"cd") != NULL) return CD;
if(strstr(cmd,"lcd") != NULL) return LCD;
return -1;
}
char* getdir(char* cmd)
{
char* fp;
//char *strtok(char *s, char *delim)//分解字符串 str 为一组字符串,delim 为分隔符,返回值:分隔符匹配到的第一个子串
fp=strtok(cmd,"|");
fp=strtok(NULL,"|");
return fp;
}
int cmd_Handler(struct msg msgs,int cfd)
{
int ret;
int fdfile;
char* dir=NULL;
//char buf[32];
ret=get_cmd_type(msgs.cmd);//将字符串转换成整形数
printf("ret:%d\n",ret);
switch(ret)
{
case PWD:
case LS:
case CD:
write(cfd,&msgs,sizeof(msgs));
break;
case GET:
write(cfd,&msgs,sizeof(msgs));
break;
case PUT:
//strcpy(buf,msgs.cmd);
dir=getdir(msgs.cmd);
if(access(dir,F_OK) == -1)
{
printf("%s not exist\n",dir);
}
else
{
fdfile=open(dir,O_RDWR);
read(fdfile,msgs.secondBuf,sizeof(msgs.secondBuf));
write(cfd,&msgs,sizeof(msgs));
close(fdfile);
}
break;
case LCD:
//printf("LCDsucess!\n");//调试信息
dir=getdir(msgs.cmd);
if(access(dir,F_OK) == -1)
{
printf("No this file!\n");
}
else
{
chdir(dir);
}
break;
case LLS:
//printf("999999\n");
system("ls");
break;
case QUIT:
//strcpy(msgs.cmd,"quit");
write(cfd,&msgs,sizeof(msgs));
close(cfd);
exit(-1);
break;
}
return ret;
}
void handler_server_message(int cfd,struct msg msgs)
{
int nread;
int fd;
struct msg msgget;
nread=read(cfd,&msgget,sizeof(msgget));//读取服务端传来的数据
if(nread == 0)
{
perror("server out!\n");;
exit(-1);
}
else if(msgget.type == DOFILE)
{
char* p=getdir(msgs.cmd);
fd= open(p,O_RDWR|O_CREAT,0600);
write(fd,msgget.cmd,strlen(msgget.cmd));
close(fd);
putchar('>');
fflush(stdout);
}
else
{
printf("------------------------\n");
printf("\n%s\n",msgget.cmd);
printf("------------------------\n");
fflush(stdout);
putchar('>');
}
}
int main(int argc,char** argv)
{
int cfd;
int ret;
struct msg msgs;
struct sockaddr_in c_addr;
memset(&c_addr,'\0',sizeof(c_addr));
if(argc != 3)//判断传入参数是否有三个
{
printf("program error!\n");
exit(-1);
}
//1.socket//创建套接字
//int socket(int domain, int type, int protocol);
cfd=socket(AF_INET,SOCK_STREAM,0);
if(cfd == -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);//把字符串形式的IP转换为网络能识别的格式
//2.connect 连接//客户连接主机
//int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
int nconnect=connect(cfd,(struct sockaddr*)&c_addr,sizeof(struct sockaddr_in));
if(nconnect == -1)
{
perror("connect");
exit(-1);
}
printf("connect......\n");
for(;;){
memset(msgs.cmd,0,sizeof(msgs.cmd));//初始化数组
scanf("%s",msgs.cmd);//获取用于输入
ret=cmd_Handler(msgs,cfd);//对输入信息进行处理,返回对应指令的值
if(ret > IFGO)//过滤错误信息
{
putchar('>');
fflush(stdout);
continue;
}
if(ret == -1)
{
printf("command not\n");
printf(">");
fflush(stdout);
continue;
}
handler_server_message(cfd,msgs);//操作服务器传递过来的数据
}
return 0;
}