项目介绍:
利用socket实现云盘的基本功能:
ls———查看服务端文件
lls———查看客户端文件
cd———切换服务端目录
lcd———切换客户端目录
put———上传文件
get———下载文件
pwd———显示路径
quit———退出
自定义一个头文件将项目所需的宏定义和结构体放在里面(注意:该头文件引用时需要使用#include" config.h"得用引号)
#define LS 0
#define GET 1
#define PWD 2
#define IFGO 3
#define LCD 4
#define LLS 5
#define CD 6
#define PUT 7
#define QUIT 8
#define DOFILE 9
struct Msg {
int type;
char cmd[1024]; //存指令
char secondbuf[128]; //存文件内容
};
服务端:
建立get_cmd_type函数对收到的指令进行变换
int get_cmd_type(char *cmd)
{
if(strcmp("ls",cmd)==0) return LS;
if(strcmp("pwd",cmd)==0) return PWD;
if(strcmp("quit",cmd)==0) return QUIT;
if(strstr(cmd,"cd")!=NULL) return CD;
if(strstr(cmd,"get")!=NULL) return GET;
if(strstr(cmd,"put")!=NULL) return PUT;
return 100;
}
ls和pwd功能实现方法相同,调用popen函数,然后调用fread读取msg.cmd的内容,在用write写入客户端显示即可
case LS:
case PWD:
msg.type = 0;
p = popen(msg.cmd,"r");
fread(msg.cmd,sizeof(msg.cmd),1,p);
write(fd,&msg,sizeof(msg));
break;
cd为切换目录,得使用chdir函数进行实现,而不能使用system否则会造成错误,在这个地方需要对切换路径名进行识别还需建立getDisDir函数获取文件名
char *getDisDir(char *csmg)
{
char *p;
p = strtok(csmg," ");
p = strtok(NULL," ");
return p;
}
case CD:
dir = getDisDir(msg.cmd);
chdir(dir);
break;
get功能从服务端下载文件到客户端,就是将文件复制到客户端,与cp指令类似
case GET:
file = getDisDir(msg.cmd);
if(access(file,F_OK)==-1){//判断文件是否存在,若不存在access返回值为-1
strcpy(msg.cmd,"Sorry no this file");
write(fd,&msg,sizeof(msg));
}
else{
msg.type = DOFILE;
//存在若存在就打开文件
fdfile = open(file,O_RDWR);
//将文件的内容读到dataBuf内
read(fdfile,dataBuf,sizeof(dataBuf));
close(fdfile);
//将dataBuf的内容复制到msg.cmd中
strcpy(msg.cmd,dataBuf);
//将所有内容全部写入客户端内
write(fd,&msg,sizeof(msg));
}
break;
put功能将客户端文件上传到服务器
case PUT:
fdfile = open(getDisDir(msg.cmd),O_RDWR|O_CREAT,0666);
write(fdfile,msg.secondbuf,strlen(msg.secondbuf));
close(fdfile);
break;
quit退出指令:
case QUIT:
printf("clint quit\n");
exit(-1);
主函数内socket编程部分
int main(int argc, char **argv)
{
//1.socket
int s_fd;
int c_fd;
int n_read;
struct Msg msg;
// char *msg ="I get you connet";
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
if(argc != 3){
printf("progam is wrong\n");
}
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]));//绔彛鍙烽渶瑕佺敤htons鍑芥暟杩涜杞崲
inet_aton(argv[1],&s_addr.sin_addr);//鍦板潃瑁呮崲api
//2.bind
bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
//3.listen
listen(s_fd,10);
int clen = sizeof(struct sockaddr_in);
while(1){
//4.accept
c_fd =accept(s_fd,(struct sockaddr *)&c_addr,&clen);
if(c_fd == -1){
perror("accept");
}
printf("get connect is %s \n",inet_ntoa(c_addr.sin_addr));//鎶婄綉缁滄牸寮忕殑IP鍦板潃瑁呮崲鎴愬瓧绗︿覆褰㈠紡
if(fork()==0){
while(1){
memset(&msg.cmd,0,sizeof(msg.cmd));
n_read=read(c_fd,&msg,sizeof(msg));
if(n_read==0){
printf("clint quit\n");
break;
}
else if(n_read>0){
msg_handler(msg,c_fd);
}
}
}
}
close(c_fd);
close(s_fd);
return 0;
}
服务端整体代码
#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
//#include<linux/in.h> 涓巒etinet/in.h鍐茬獊:浜?#include <arpa/inet.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include"config.h"
//鐢ㄤ簬cmd鐨勮浆鎹?int get_cmd_type(char *cmd)
{
if(strcmp("ls",cmd)==0) return LS;
if(strcmp("pwd",cmd)==0) return PWD;
if(strcmp("quit",cmd)==0) return QUIT;
if(strstr(cmd,"cd")!=NULL) return CD;
if(strstr(cmd,"get")!=NULL) return GET;
if(strstr(cmd,"put")!=NULL) return PUT;
return 100;
}
char *getDisDir(char *csmg)
{
char *p;
p = strtok(csmg," ");
p = strtok(NULL," ");
return p;
}
//鎵цcmd
void msg_handler(struct Msg msg,int fd)
{
int ret;
FILE *p;
char *dir;
char *file=NULL;
int fdfile;
char dataBuf[1024]={0};
printf("cmd:%s \n",msg.cmd);
ret = get_cmd_type(msg.cmd);
switch(ret){
case LS:
case PWD:
msg.type = 0;
p = popen(msg.cmd,"r");
fread(msg.cmd,sizeof(msg.cmd),1,p);
write(fd,&msg,sizeof(msg));
break;
case CD:
msg.type = 1;
dir = getDisDir(msg.cmd);
chdir(dir);
break;
case GET:
file = getDisDir(msg.cmd);
if(access(file,F_OK)==-1){
strcpy(msg.cmd,"Sorry no this file");
write(fd,&msg,sizeof(msg));
}
else{
msg.type = DOFILE;
fdfile = open(file,O_RDWR);
read(fdfile,dataBuf,sizeof(dataBuf));
close(fdfile);
strcpy(msg.cmd,dataBuf);
write(fd,&msg,sizeof(msg));
}
break;
case PUT:
fdfile = open(getDisDir(msg.cmd),O_RDWR|O_CREAT,0666);
write(fdfile,msg.secondbuf,strlen(msg.secondbuf));
close(fdfile);
break;
case QUIT:
printf("clint quit\n");
exit(-1);
}
}
int main(int argc, char **argv)
{
//1.socket
int s_fd;
int c_fd;
int n_read;
struct Msg msg;
// char *msg ="I get you connet";
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
if(argc != 3){
printf("progam is wrong\n");
}
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]));//绔彛鍙烽渶瑕佺敤htons鍑芥暟杩涜杞崲
inet_aton(argv[1],&s_addr.sin_addr);//鍦板潃瑁呮崲api
//2.bind
bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
//3.listen
listen(s_fd,10);
int clen = sizeof(struct sockaddr_in);
while(1){
//4.accept
c_fd =accept(s_fd,(struct sockaddr *)&c_addr,&clen);
if(c_fd == -1){
perror("accept");
}
printf("get connect is %s \n",inet_ntoa(c_addr.sin_addr));//鎶婄綉缁滄牸寮忕殑IP鍦板潃瑁呮崲鎴愬瓧绗︿覆褰㈠紡
if(fork()==0){
while(1){
memset(&msg.cmd,0,sizeof(msg.cmd));
n_read=read(c_fd,&msg,sizeof(msg));
if(n_read==0){
printf("clint quit\n");
break;
}
else if(n_read>0){
msg_handler(msg,c_fd);
}
}
}
}
close(c_fd);
close(s_fd);
return 0;
}
客户端:
在客户端中实现GET,LS,CD,PWD,的方法是一致的,只需向服务器发送指令即可,
switch(ret){
case CD:
case PWD:
case LS:
case GET:
write(fd,&msg,sizeof(msg));
break;
put功能:
case PUT:
dir = getDir(msg.cmd);
if(access(dir,F_OK)==-1){//判断文件是否存在
printf("%s this file no exit\n",dir);
}
else{
fdfile=open(dir,O_RDWR);//打开文件
read(fdfile,msg.secondbuf,sizeof(msg.secondbuf));//将内容往sg.secondbu读
close(fdfile);
write(fd,&msg,sizeof(msg));
}
break;
lcd,lls quit指令:
case LCD:
dir = getDir(msg.cmd);
chdir(dir);
break;
case LLS:
system("ls");
break;
case QUIT:
strcpy(msg.cmd,"quit");
write(fd,&msg,sizeof(msg));
close(fd);
exit(-1);
}
return ret;
}
对服务器数据的处理,首先还是判断服务器是否连接,之后对get指令进行判断,剩下的功能都是直接打印客户端或者服务端的信息
void c_msg_handler(struct Msg msg,int fd)
{
int n_read;
struct Msg msgget;
int newfdfile;
char *filename;
n_read =read(fd,&msgget,sizeof(msgget));
if(n_read == 0){
printf("sever is quit\n");
exit(-1);
}
else if(msgget.type == DOFILE){//在服务端进行的设计
filename=getDir(msg.cmd);
newfdfile=open(filename,O_RDWR|O_CREAT,0666);
write(newfdfile,&msgget.cmd,strlen(msgget.cmd));
close(newfdfile);
fflush(stdout);
}
else{
printf("---------------------\n");
printf("%s\n",msgget.cmd);
printf("---------------------\n");
fflush(stdout);
}
}
服务端整体代码
#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
//#include<linux/in.h> 涓巒etinet/in.h鍐茬獊:浜?#include <arpa/inet.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include"config.h"
int get_cmd_type(char *cmd)
{
if(strcmp("lls",cmd)==0) return LLS;
if(strcmp("ls",cmd)==0) return LS;
if(strcmp("pwd",cmd)==0) return PWD;
if(strcmp("quit",cmd)==0) return QUIT;
if(strstr(cmd,"cd")!=NULL) return CD;
if(strstr(cmd,"get")!=NULL) return GET;
if(strstr(cmd,"put")!=NULL) return PUT;
if(strstr(cmd,"lcd")!=NULL) return LCD;
return -1;
}
char *getDir(char *cmd)
{
char *p;
p = strtok(cmd," ");
p = strtok(NULL," ");
return p;
}
int cmd_handler(struct Msg msg,int fd)
{
int ret;
char *dir=NULL;
int fdfile;
char buf[32];
ret = get_cmd_type(msg.cmd);
switch(ret){
case CD:
case PWD:
case LS:
case GET:
write(fd,&msg,sizeof(msg));
break;
case PUT:
strcpy(buf,msg.cmd);
dir = getDir(buf);
if(access(dir,F_OK)==-1){
printf("%s this file no exit\n",dir);
}
else{
fdfile=open(dir,O_RDWR);
read(fdfile,msg.secondbuf,sizeof(msg.secondbuf));
close(fdfile);
write(fd,&msg,sizeof(msg));
}
break;
case LCD:
dir = getDir(msg.cmd);
chdir(dir);
break;
case LLS:
system("ls");
break;
case QUIT:
strcpy(msg.cmd,"quit");
write(fd,&msg,sizeof(msg));
close(fd);
exit(-1);
}
return ret;
}
void c_msg_handler(struct Msg msg,int fd)
{
int n_read;
struct Msg msgget;
int newfdfile;
char *filename;
n_read =read(fd,&msgget,sizeof(msgget));
if(n_read == 0){
printf("sever is quit\n");
exit(-1);
}
else if(msgget.type == DOFILE){
filename=getDir(msg.cmd);
newfdfile=open(filename,O_RDWR|O_CREAT,0666);
write(newfdfile,&msgget.cmd,strlen(msgget.cmd));
close(newfdfile);
fflush(stdout);
}
else{
printf("---------------------\n");
printf("%s\n",msgget.cmd);
printf("---------------------\n");
fflush(stdout);
}
}
int main(int argc, char **argv)
{
//1.socket
int c_fd;
int n_read;
struct sockaddr_in c_addr;
struct Msg msg;
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]));//绔彛鍙烽渶瑕佺敤htons鍑芥暟杩涜杞崲
inet_aton(argv[1],&c_addr.sin_addr);//鍦板潃瑁呮崲api
//connect
if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr_in))==-1){
perror("connect");
exit(-1);
}
printf("connecting ...\n ");
while(1){
memset(msg.cmd,0,sizeof(msg.cmd));
gets(msg.cmd);
int ret = cmd_handler(msg,c_fd);
if(ret>IFGO){
continue;
}
if(ret==-1){
printf("cmd error,please put new cmd\n");
continue;
}
c_msg_handler(msg,c_fd);
}
return 0;
}