服务器
#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include<string.h>
#include <unistd.h>
#include<string.h>
#include "config.h"
#include <sys/stat.h>
#include <fcntl.h>
char * getDesDir(char *str)
{
char *token;
token = strtok(str," ");
token = strtok(NULL," ");
int i=0;//去除fgets函数输入后带的'\n'字符,将'\n'用'\0'替换
//否则后面的函数执行的语句后面会带一个'\n',导致不能改变目录。
while(token[i]!='\n'){
i++;
}
token[i]='\0';
return token;
}
int get_cmd_type(struct Msg msg)
{
if(!strcmp("ls\n",msg.cmd)) return LS;//这后面加'\n'是因为客户端输入命令用的是fgets函数,会带一个'\n',这里不加的话会比较不出来。
if(!strcmp("quit\n",msg.cmd)) return QUIT;
if(!strcmp("pwd\n",msg.cmd)) return PWD;
if(!strcmp("cd\n",msg.cmd)) return 100;//为了避免客户端单独输入cd导致运行getDesDir函数时出错,且单纯一个字符串"cd"对chdir函数来说本来就是不能执行的
if(strstr(msg.cmd,"cd") != NULL) return CD;
if(strstr(msg.cmd,"get") != NULL) return GET;
if(strstr(msg.cmd,"put") != NULL) return PUT;
return 100;
}
void msg_handler(struct Msg msg,int fd)
{
int ret;
int filefd;
FILE *fp;
char *dir=NULL;
char *file_name=NULL;
struct Msg readmsg;
memset(&readmsg,'\0',sizeof(readmsg));
ret=get_cmd_type(msg);
printf("client:%s\n",msg.cmd);
switch(ret){
case LS:
case PWD:
fp=popen(msg.cmd,"r");//这里使用popen函数是应为popen可以把执行结果存到文件里面,可以发送给客户端system和execl函数做不到
fread(msg.cmd,sizeof(msg.cmd),1,fp);
write(fd,&msg,sizeof(msg));
fclose(fp);
break;
case CD:
dir=getDesDir(msg.cmd);
chdir(dir);//这里不能用system和popen,这两个函数不能改变路径
break;
case GET:
strcpy(readmsg.cmd,msg.cmd);
file_name=getDesDir(msg.cmd);
if(access(file_name,F_OK)==-1){//判断文件是否存在
strcpy(msg.cmd,"No find this file!");
write(fd,&msg,sizeof(msg));
}else{
filefd=open(file_name,O_RDWR);
read(filefd,readmsg.file_content,sizeof(readmsg.file_content));
write(fd,&readmsg,sizeof(readmsg));
close(filefd);
}
break;
case PUT:
filefd=open(getDesDir(msg.cmd),O_RDWR|O_CREAT,0600);
write(filefd,msg.file_content,strlen(msg.file_content));
close(filefd);
break;
case QUIT:
printf("client quit\n");
exit(-1);
}
}
int main(int argc,char **argv)
{
if(argc!=3){
printf("argc");
}
int s_fd;
int c_fd;
int n_read;
struct Msg msg;
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
int size=sizeof(c_addr);
memset(&s_addr,0,sizeof(s_addr));
memset(&c_addr,0,sizeof(c_addr));
s_addr.sin_family=AF_INET;
s_addr.sin_port=htons(atoi(argv[2]));//host to net把为主机字节序的端口号转换成网络字节序(大端字节序)
inet_aton(argv[1],&s_addr.sin_addr);//把IP地址的ascll转换成网络字节序
//socket
if((s_fd=socket(AF_INET,SOCK_STREAM,0))==-1){
perror("socket");
}
//bind
if(bind(s_fd,(struct sockaddr *)&s_addr,sizeof( struct sockaddr_in))==-1){
perror("bind");
}
listen(s_fd,10);
//accept
while(1){
//accept
int c_fd=accept(s_fd,(struct sockaddr *)&c_addr,&size);
printf("clicent success!\n");
if(fork()==0){
while(1){
memset(&msg,0,sizeof(msg));
n_read=read(c_fd,&msg,sizeof(msg));
if(n_read==0){
printf("client out!\n");
break;
}else if(n_read>0){
msg_handler(msg,c_fd);
}
}
}
}
close(s_fd);
close(c_fd);
return 0;
}
客服端
#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include<string.h>
#include <unistd.h>
#include<string.h>
#include "config.h"
#include <sys/stat.h>
#include <fcntl.h>
char * getDesDir(char *str)
{
char *token;
token = strtok(str," ");
token = strtok(NULL," ");
int i=0;//去除fgets函数输入后带的'\n'字符,将'\n'用'\0'替换
//否则后面的函数执行的语句后面会带一个'\n',导致不能改变目录。
while(token[i]!='\n'){
i++;
}
token[i]='\0';
return token;
}
void server_msg_handler(struct Msg msg)
{
int filefd;
char *file_name=NULL;
if(strstr(msg.cmd,"get") != NULL){
filefd=open(getDesDir(msg.cmd),O_RDWR|O_CREAT,0600);
write(filefd,msg.file_content,strlen(msg.file_content));
close(filefd);
}
else{
printf("%s\n",msg.cmd);
}
}
int get_cmd_type(struct Msg msg)
{
if(!strcmp("ls\n",msg.cmd)) return LS;//这后面加'\n'是因为客户端输入
//命令用的是fgets函数,会带一个'\n',这里不加的话会比较不出来。
if(!strcmp("quit\n",msg.cmd)) return QUIT;
if(!strcmp("pwd\n",msg.cmd)) return PWD;
if(!strcmp("cd\n",msg.cmd)) return 100;//为了避免客户端单独输入cd导>致运行getDesDir函数时出错,且单纯一个字符串"cd"对chdir函数来说本来就是不能执行的
if(strstr(msg.cmd,"cd") != NULL&strstr(msg.cmd,"lcd")==NULL)
return CD;
//确保cd xx和lcd xx命令不会冲突
if(strstr(msg.cmd,"get") != NULL) return GET;
if(strstr(msg.cmd,"put") != NULL) return PUT;
if(!strcmp("lls\n",msg.cmd)) return LLS;
if(strstr(msg.cmd,"lcd")!=NULL) return LCD;
if(!strcmp("lpwd\n",msg.cmd)) return LPWD;
return 100;
}
void cmd_handler(int c_fd,struct Msg msg)
{
int ret;
int filefd;
char *file_name=NULL;
char *dir=NULL;
struct Msg readmsg;
memset(&readmsg,'\0',sizeof(readmsg));
ret=get_cmd_type(msg);
switch(ret){
case LS:
case PWD:
case CD:
case GET:
write(c_fd,&msg,sizeof(msg));
break;
case PUT:
strcpy(readmsg.cmd,msg.cmd);//执行了下面的函数以后cmd命令就会只剩一个put了
//为了确保命令能发到服务端去,这里新建了一个结
//构体,把命令和要上传的文件的内容存在cmd和file_content里。
file_name=getDesDir(msg.cmd);
if(access(file_name,F_OK)==-1){//判断文件是否存在
printf("No this file!\n");
}else{
filefd=open(file_name,O_RDWR);
}
if(filefd==-1){
perror("open defeat!");
}
else{
read(filefd,readmsg.file_content,sizeof(readmsg.file_content));
write(c_fd,&readmsg,sizeof(readmsg));
close(filefd);
}
break;
case LPWD:
system("pwd");
break;
case LLS:
system("ls");
break;
case LCD:
dir=getDesDir(msg.cmd);
int i=chdir(dir);
if(i==-1){
printf("chdir defeat!\n");
}
break;
case QUIT:
write(c_fd,&msg,sizeof(msg));
printf("client quit!\n");
close(c_fd);
exit(-1);
}
}
int main(int argc,char **argv)
{
if(argc!=3){
printf("argc");
}
int c_fd;
int n_read;
struct Msg msg;
struct sockaddr_in c_addr;
int size=sizeof(c_addr);
memset(&c_addr,0,sizeof(c_addr));
c_addr.sin_family=AF_INET;
c_addr.sin_port=htons(atoi(argv[2]));
inet_aton(argv[1],&c_addr.sin_addr);
//int socket(int domain, int type, int protocol);
if((c_fd=socket(AF_INET,SOCK_STREAM,0))==-1){
perror("socket");
}
//int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
int con_err=connect(c_fd,( struct sockaddr *)&c_addr,size);
if(con_err==-1){
perror("connnect");
exit(-1);
}
printf("connect success>\n");
while(1){
if(fork()==0){
while(1){
memset(&msg,0,sizeof(msg));
n_read=read(c_fd,&msg,sizeof(msg));
if(n_read==0){
printf("server out!\n");
break;
}else if(n_read>0){
server_msg_handler(msg);
}
}
}
else{
while(1){
memset(&msg,0,sizeof(msg));
fgets(msg.cmd,128,stdin);
cmd_handler(c_fd,msg);/*cmd_handler函数用来区分是本地命令(lcd lpwd lls等)
还是服务器指令(ls cd pwd get put qiut等),本地指令直接调用system,
不需要发给服务器,服务器指令需要发给服务器。*/
}
}
break;
}
close(c_fd);
return 0;
}
头文件
#define LS 0
#define GET 1
#define PWD 2
#define CD 3
#define LCD 5
#define LLS 6
#define PUT 7
#define LPWD 8
#define QUIT 9
struct Msg
{
char cmd[1024];//存放客户端指令
char file_content[1024];//存放文件的内容,get xx文件和put xx文件时需要把文件内容放到这里面
};