功能需求:
远程操作:
①获取服务器的文件: get xxx
②显示服务器有哪些文件: ls
③进入服务器某文件夹: cd xxx;
④上传文件到服务器: put xxx
⑤打印当前服务器路径: pwd
⑥退出服务器: quit
本地操作:
①查看客户端本地文件: lls
②进入客户端文件夹: lcd
实现的基本思路:
查看本地文件lls:可以直接使用system函数直接调用;显示服务器文件ls:则可以通过socket套接字来实现数据传输,然后用popen函数运行服务器ls这个api再通过read函数将ls展开的数据读出来,再通过write函数写到客户端,put、get均是以上思路
代码实现
头文件 server.h
#define LS 0
#define CD 1
#define PWD 2
#define GET 3
#define IFRET 4
#define LLS 5
#define LCD 6
#define PUT 7
#define QUIT 8
#define DOFILE 9
struct Msg //传递的信息结构体
{
int type ; //服务器返回类型,0表示不用返回,1表示字符串,DOFILE表示要创建文件
char data[32]; //指令
char secondBuf[10240];//数据,用于server和client间的通信
};
服务器代码
socket套接字->bind绑定网络地址和端口号->listen监听->while循环 accept阻塞等待客户端连接->如果有客户端连接,就fork()产生子进程来对接客户端(一个客户端一个子进程)->read读客户端发送的请求命令,如果读到了命令,就进入msghandler函数处理命令
#include<stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
//#include<linux/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <string.h>
#include <unistd.h>
#include"config.h"
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
/*struct sockaddr_in {
sa_family_t sin_family; //协议族
in_port_t sin_port; //端口号
struct in_addr sin_addr; //IP地址结构体
unsigned char sin_zero[8]; //填充,没有实际意义,只是为更sockaddr结构在内存中相互对齐,这样才能相互转换
}*/
/*struct in_addr {
__be32 s_addr;
};*/
char* getdestdir(char *cmd)
{
char* p = NULL;
p=strtok(cmd," ");
p=strtok(NULL," ");
return p;
}
int get_cmd_type(char *cmd)
{
if(!strcmp("ls",cmd)) return LS;
if(!strcmp("lls",cmd)) return LLS;
if(!strcmp("pwd",cmd)) return PWD;
if(!strcmp("quit",cmd)) return QUIT;
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;
}
int msghandler(int fd , struct Msg msg)
{
char* file;
char* dir;
char readbuf[1024]={0};
int fdfile;
int ret = get_cmd_type(msg.data);
switch(ret){
case LS:
case PWD:
msg.type = 1;
FILE* r=popen(msg.data,"r");//popen是执行msg.data的命令然后将执行结果返回给FILE*r
fread(msg.secondBuf,sizeof(msg.secondBuf),1,r);//将r中的结果读到msg.secondBuf中
write(fd,&msg,sizeof(msg));//将整个结构体再通过管道发回给客户端
break;
case LLS:
msg.type = 1;
write(fd,&msg,sizeof(msg));