使用说明
运行操作
-
运行服务端
./server 本机IP地址 端口号(使用ifconfig查看本机IP地址)
-
运行客户端
./client IP地址 相同端口号
指令说明
- ls —— 查看服务端当下目录
- lls —— 查看客户端当下目录
- pwd —— 查看服务端当前路径
- quit —— 客户端退出连接
- cd name —— 令服务器进入到name路径下下
- get name —— 从服务器上下载name文件
- put name —— 将客户端name文件上传到服务器
头文件define.h
#define LS 0
#define GET 1
#define PWD 2
#define CD 3
#define IFGO 4
#define LCD 5
#define LLS 6
#define PUT 7
#define QUIT 8
#define DOFILE 9
struct Msg //数据传递中转变量
{
int type;
char cmd[1024];
char secondBuf[1024];
};
~
服务器server.c
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include"define.h"
#include <sys/stat.h>
#include <fcntl.h>
void delchar(char *dir,char change[10]) //将指针字符串dir后\n删除后放到数组change中
{
sprintf(change,"%s",dir);
int size = strlen(dir);
change[size-1] = '\0';
}
char *getDesDir(char *cmsg) //获取某些命令后的参数如指令"cd .."中的".."
{
char *p;
p = strtok(cmsg," ");
p = strtok(NULL," ");
return p;
}
int get_cmd_type(char *cmd) //接收客户端传来的数据后通过对比确定命令是什么
{
if(!strcmp("ls\n",cmd)) return LS;
if(!strcmp("quit\n",cmd)) return QUIT;
if(!strcmp("pwd\n",cmd)) return PWD;
if(strstr(cmd,"cd") != NULL) return CD;
if(strstr(cmd,"get") != NULL) return GET;
if(strstr(cmd,"put") != NULL) return PUT;
}
void msg_handler(struct Msg msg, int fd) //根据客户端传来的命令做出对应反应
{
char dataBuf[1024] = {0};
char *file = NULL;
int fdfile;
int ret = get_cmd_type(msg.cmd); //获取命令对应的数字
switch(ret){ //根据数字执行命令
case LS:
case PWD:
msg.type = 0;
FILE *fp = popen(msg.cmd,"r"); //直接使用传来的命令
fread(msg.cmd,sizeof(msg.cmd),1,fp); //将获取的数据读到msg.cmd中
write(fd,&msg,sizeof(msg)); //将数据发回客户端
break;
case CD:
msg.type = 1;
char *dir = getDesDir(msg.cmd); //分离指令后的参数
char CD_Change[10];
delchar(dir,CD_Change); //删除命令后\n(由于使用fgets获取字符串会自动加\n)
chdir(CD_Change); //进入到目标的路径下
break;
case GET:
file = getDesDir(msg.cmd); //分离出要获取的文件名
char GET_Change[10];
delchar(file,GET_Change); //删除\n
if(access(GET_Change,F_OK) == -1){ //判断是否存在输入文件名
strcpy(msg.cmd,"No this file!");
write(fd,&msg,sizeof(msg));
}else{
msg.type = DOFILE;
fdfile = open(GET_Change,O_RDWR); //打开要下载的文件
read(fdfile,dataBuf,sizeof(dataBuf)); //将文件信息读到dataBuf中
close(fdfile);
strcpy(msg.cmd,dataBuf); //将文件数据复制给msg.cmd
write(fd,&msg,sizeof(msg)); //传回客户端
}
break;
case PUT:
file = getDesDir(msg.cmd); //分离出要上传的文件名
char PUT_Change[10];
delchar(file,PUT_Change); //删除\n
fdfile = open(PUT_Change,O_RDWR|O_CREAT,0600); //创建并打开该名文件
write(fdfile,msg.secondBuf,strlen(msg.secondBuf)); //写客户端传来的数据
close(fdfile);
break;
case QUIT:
printf("client quit\n/");
exit(-1);
}
}
int main(int argc,char **argv)
{
int s_fd;
int c_fd;
int n_read;
int clen = sizeof(struct sockaddr_in);
char readBuf[128];
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_in)); //绑定数据
listen(s_fd,10); //监听客户端
while(1)
{
c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&clen); //等待接受客户端连接(没有连接阻塞)
if(c_fd == -1) //判断是否连接成功
{
perror("accept");
}
printf("get connect:%s\n",inet_ntoa(c_addr.sin_addr));
if(fork() == 0) //建立子进程,父进程继续等待客户端连接
{
while(1){
memset(readBuf,0,sizeof(readBuf)); //清空readBuf
n_read = read(c_fd,&msg,sizeof(msg)); //接受客户端发送的指令(没有则阻塞)
if(n_read == 0) //判断
{
perror("client out\n");
break;
}else if(n_read > 0){
msg_handler(msg,c_fd); //将指令传入msg_handler函数进行判断
}
}
}
}
close(c_fd);
close(s_fd);
return 0;
}
客户端client
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include"define.h"
#include <sys/stat.h>
#include <fcntl.h>
void delchar(char *dir,char change[10]) //将指针字符串dir后\n删除后放到数组change中
{
sprintf(change,"%s",dir);
int size = strlen(dir);
change[size-1] = '\0';
}
char *getdir(char *cmd) //获取某些命令后的参数如指令"cd .."中的".."
{
char *p;
p = strtok(cmd," ");
p = strtok(NULL," ");
return p;
}
int get_cmd_type(char *cmd) //接收客户端传来的数据后通过对比确定命令是什么
{
if(strstr(cmd,"lcd") != NULL) return LCD;
if(!strncmp("ls\n",cmd,sizeof(cmd))) return LS;
if(!strncmp("quit\n",cmd,sizeof(cmd))) return QUIT;
if(!strncmp("pwd\n",cmd,sizeof(cmd))) return LS;
if(!strncmp("lls\n",cmd,sizeof(cmd))) return LLS;
if(strstr(cmd,"cd") != NULL) return CD;
if(strstr(cmd,"get") != NULL) return GET;
if(strstr(cmd,"put") != NULL) return PUT;
return -1;
}
int cmd_handler(struct Msg msg, int fd) //根据客户端传来的命令做出对应反应
{
char *dir = NULL;
char buf[32];
int ret=0;
int filefd;
ret = get_cmd_type(msg.cmd); //获取命令对应的数字
switch(ret){ //根据数字执行对于命令
case CD:
case LS:
case PWD:
msg.type = 0;
write(fd,&msg,sizeof(msg)); //将命令发给服务端
break;
case GET:
msg.type = 2;
write(fd,&msg,sizeof(msg)); //将命令发给服务端
break;
case PUT:
strcpy(buf,msg.cmd);
dir = getdir(buf); //分离命令中文件名
char PutFileName[10];
delchar(dir,PutFileName); //删除\n
if(access(PutFileName,F_OK) == -1){ //判断文件是否存在
z printf("%s not exsit\n",dir);
}else{
filefd = open(PutFileName,O_RDWR); //打开文件
read(filefd,msg.secondBuf,sizeof(msg.secondBuf)); //读取文件数据
close(filefd);
write(fd,&msg,sizeof(msg)); //将文件数据发给服务端
}
break;
case LLS:
system("ls"); //直接执行ls指令
break;
case LCD:
dir = getdir(msg.cmd); //分离文件名
chdir(dir); //进入所在路径
break;
case QUIT:
write(fd,&msg,sizeof(msg));
exit(-1);
}
return ret;
}
void handler_server_message(int c_fd,struct Msg msg)
{
int n_read;
struct Msg msgget;
int newfilefd;
n_read = read(c_fd,&msgget,sizeof(msgget)); //读取服务端传回来的文件数据
if(n_read == 0){
printf("server is out,quit\n");
exit(-1);
}
else if(msgget.type == DOFILE){ //针对服务端GET的操作
char *p = getdir(msg.cmd);
char filename[10];
delchar(p,filename);
w
newfilefd = open(filename,O_RDWR|O_CREAT,0600); //将服务端下载好的数据建同名文件
write(newfilefd,msgget.cmd,strlen(msgget.cmd)); //将数据录入进去
putchar('>');
fflush(stdout);
close(newfilefd);
}
else{
printf("------------------------------------------\n");
printf("%s\n",msgget.cmd);
printf("------------------------------------------\n");
putchar('>');
fflush(stdout);
}
}
int main(int argc,char **argv)
{
int c_fd;
int n_read;
char readBuf[128];
struct Msg msg;
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);
}
printf("connect...\n");
int mark = 0;
while(1)
{
memset(msg.cmd,0,sizeof(msg.cmd));
if(mark == 0) printf(">"); //为了美观>的处理
fgets(msg.cmd,sizeof(msg.cmd),stdin); //获取命令
if(strlen(msg.cmd) == 0){
if(mark == 1){
printf(">");
}
continue;
}
mark == 1;
int ret = cmd_handler(msg,c_fd); //根据指令做出的相关操作
if(ret >= CD) //对于CD PWD等指令无需后续步骤
{
putchar('>');
fflush(stdout);
continue;
}
if(ret == -1) //判断输入指令是否存在
{
printf("command not\n");
printf(">");
fflush(stdout);
continue;
}
handler_server_message(c_fd,msg); //打印所得到的数据
}
close(c_fd);
return 0;
}