项目思路与功能实现
socket网络编程建立服务端与客户端的连接,文件编程实现客户端与服务端数据通信,客户端通过获取用户输入的命令,进行相关的命令识别和处理,服务端通过检测客户端发送的命令,执行相应的操作,并将执行命令所获得的数据发送给客户端。
get+xxx:实现客户端远程从服务器端获取文件
put+xxx:实现客户端上传文件到服务器端
cd+xxx:实现服务器切换目录的操作
lcd+xxx:实现客户端切换目录的操作
ls、pwd:实现查看服务器当前目录的操作
lls:实现查看客户端当前目录下文件
quit:实现客户端的退出操作
服务端代码
#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include<string.h>
#include"config.h"
#include <sys/stat.h>
#include <fcntl.h>
int get_cmd(char cmd[128])
{
if(!strcmp("ls",cmd)) return LS;
if(!strcmp("pwd",cmd)) return PWD;
if(!strcmp("quit",cmd)) return QUIT;
if(strstr(cmd,"cd")!=NULL) return CD;
if(strstr(cmd,"get")!=NULL) return GET;
if(strstr(cmd,"put")!=NULL) return PUT;
return -1;
}
char *get_dir(char *cmd)//此函数用于从指令中中剥离出文件名
{
char *p;
p=strtok(cmd," ");
p=strtok(NULL," ");
return p;
}
void handler_msg(int fd,struct Msg msg)
{
int ret;
int fdfile;
FILE *fp;
char readbuff[1024]={0};
char *p=NULL;
char *file=NULL;
printf("->%s\n",msg.cmd);//打印客户端指令
ret = get_cmd(msg.cmd);
switch(ret){
case LS:
case PWD:
fp=popen(msg.cmd,"r");
if(fp == NULL)
{
printf("popen error!\n");
exit(-1);
}
memset(msg.data,0,sizeof(msg.data));
fread(msg.data,sizeof(msg.data),1,fp);
write(fd,&msg,sizeof(msg));//将ls或pwd的内容写到客户端 客户端打印出msg.data内容
pclose(fp);
break;
case CD:
p = get_dir(msg.cmd);//剥离出cd后边的指令
chdir(p);//chdir改变当前工作目录 参数为目标目录
break;
case GET:
file = get_dir(msg.cmd); //剥离出get后边的指令
if(access(file,F_OK)==-1)//如果服务端没有这个文件
{
strcpy(msg.data,"No such file found\n");
write(fd,&msg,sizeof(msg));
}else{
fdfile=open(file,O_RDWR);
if(read(fdfile,readbuff,sizeof(readbuff))==0)
{
printf("GET:read error\n");
}
close(fdfile);
strcpy(msg.data,readbuff);
write(fd,&msg,sizeof(msg));//将readbuff传到客户端
}
break;
case PUT:
fdfile=open(get_dir(msg.cmd),O_RDWR|O_CREAT,0666);
if(fdfile == -1)
{
printf("PUT:Open failed\n");
perror("open");
}
write(fdfile,msg.data,sizeof(msg.data));//将data内容写到fdfile中
close(fdfile);
system("ls");
break;
case QUIT:
printf("client is quit\n");
close(fd);
exit(-1);
printf("also quit!");
break;
}
}
int main(int argc,char **argv)
{
int s_fd;
int c_fd;
int n_read;
struct Msg msg;
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));
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);
bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr));
listen(s_fd,10);
int len = sizeof(struct sockaddr_in);
while(1){
c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&len);
if(c_fd == -1)
{
perror("accept:");
exit(-1);
}
printf("get connect%s\n",inet_ntoa(c_addr.sin_addr));
if(fork() == 0)
{
while(1)
{
memset(msg.cmd,0,sizeof(msg.cmd));//清空msg.cmd
n_read = read(c_fd,&msg,sizeof(msg));//读c_fd指向的文件 将客户端的内容放在msg中
if(n_read == 0)
{
printf("Client Exit\n");
break;
}else if(n_read > 0)
{
handler_msg(c_fd,msg);//操作客户端发送来的指令
}
}
}
}
close(s_fd);
close(c_fd);
return 0;
}
config.h
#define QUIT 0
#define LCD 1
#define CD 2
#define LLS 3
#define PUT 4
#define DOFILE 5
#define PWD 6
#define GET 7
#define LS 8
#define IFFILE 9
struct Msg{
int type;
char cmd[128];
char data[1024];
};
客户端代码
#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<stdlib.h>
#include <unistd.h>
#include<string.h>
#include"config.h"
#include <sys/stat.h>
#include <fcntl.h>
int get_cmd(char cmd[128])
{
if(!strcmp("ls",cmd)) return LS;
if(!strcmp("pwd",cmd)) return PWD;
if(!strcmp("quit",cmd)) return QUIT;
if(!strcmp("lls",cmd)) return LLS;
if(strstr(cmd,"lcd")!=NULL) return LCD;
if(strstr(cmd,"cd")!=NULL) return CD;
if(strstr(cmd,"get")!=NULL) return GET;
if(strstr(cmd,"put")!=NULL) return PUT;
return -1;
}
char *get_dir(char *cmd)
{
char *p;
p=strtok(cmd," ");
p=strtok(NULL," ");
return p;
}
int handler_client(int fd,struct Msg msg)
{
int ret;
int fdfile;
char*file;
char *p=NULL;
char readbuff[1024]={0};
struct Msg put;
strcpy(put.cmd,msg.cmd);
ret = get_cmd(msg.cmd);
switch(ret){
case LLS:
puts("---------------------\n");
system("ls");
break;
case LCD:
p = get_dir(msg.cmd);
chdir(p);//chdir改变当前工作目录 参数为目标目录
break;
case LS:
case PWD:
case CD:
write(fd,&msg,sizeof(msg));
break;
case GET:
write(fd,&msg,sizeof(msg));
break;
case PUT:
file = get_dir(msg.cmd);
fdfile = open(file,O_RDWR);
read(fdfile,readbuff,sizeof(readbuff));
close(fdfile);
memset(put.data,0,sizeof(put.data));
strcpy(put.data,readbuff);
write(fd,&put,sizeof(put));//将put内容写到服务端
break;
case QUIT:
write(fd,&msg,sizeof(msg));
close(fd);
exit(-1);
break;
}
return ret;
}
void handler_server_msg(int fd,struct Msg msg)
{
int n_read;
int file;
char *p=NULL;
struct Msg getmsg;
n_read=read(fd,&getmsg,sizeof(getmsg));
if(n_read == 0)
{
printf("client is not ok\n");
exit(-1);
}else if(getmsg.type == IFFILE)
{
p = get_dir(msg.cmd);
file = open(p,O_RDWR|O_CREAT,0666);
write(file,getmsg.data,sizeof(getmsg.data));
close(file);
fflush(stdout);//清空输出缓冲区
}else{
printf("------------------------\n");
printf("\n%s\n",getmsg.data);
printf("------------------------\n");
fflush(stdout);//清空输出缓冲区
}
}
int main(int argc,char **argv)
{
int c_fd;
int n_read;
struct Msg msg;
struct sockaddr_in c_addr;
if(argc != 3)
{
printf("parameter error\n");
exit(-1);
}
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);
}
printf("connect success ip:%s\n",inet_ntoa(c_addr.sin_addr));//打印ip
while(1)
{
if(memset(msg.cmd,0,sizeof(msg.cmd))==NULL)
{
printf("memset error\n");
exit(0);
}
printf("> ");
gets(msg.cmd);//键盘输入给cmd
int ret =handler_client(c_fd,msg); //指令给ret
if(ret<DOFILE)//如果小于5 是quit lcd cd lls put 如果大于5是pwd get ls
{
fflush(stdout);
continue;
}else if(ret == -1)
{
printf("input error\n");
fflush(stdout);//清空输出缓冲区
continue;
}
handler_server_msg(c_fd,msg);
}
close(c_fd);
return 0;
}
运行结果