目录
1、功能
1.1服务端
1.接收客户端指令,实现如下的操作:
ls,rm,cd,pwd
上传和下载文件操作(get,put)
断开连接quit
1.2客户端
1.给服务器发送指令,实现相关操作
ls,rm,cd,pwd,get,put
2.客户端自身指令
lls,lrm,lcd,lpwd
3.退出程序指令quit
2、相关API
2.1初始化变量memset
void *memset(void *s, int c, size_t n);
/*用法例子*/
struct Mcc buf;
memset(&buf,'\0',sizeof(buf));
printf("%ld\n",sizeof(buf));
printf("set:%d\n",buf.set);
printf("type:%d\n",buf.type);
printf("cmd:%s\n",buf.cmd);
printf("data:%s\n",buf.data);
printf("%ld\n",sizeof(struct Mcc));
return 0;
/*输出结果
1160
set:0
type:0
cmd:
data:
1160
*/
功能:初始化赋值
参数1:任意类型变量,可以是结构体
参数2:赋的初值,常用0或者’\0’
参数3:长度,sizeof可以是变量也可以是数据类型
2.2判断文件是否存在access
int access(const char *pathname, int mode);
返回值:不存在返回-1
参数1:文件名字
参数2:这里用F_OK
R_OK 只判断是否有读权限
W_OK 只判断是否有写权限
X_OK 判断是否有执行权限
F_OK 只判断是否存在
2.3执行系统命令popen
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
/*用法例子*/
struct Mcc buf;
memset(&buf,'\0',sizeof(buf));
FILE *f = popen("ls","r");
fread(buf.data,1024,1,f);
printf("open:%s",buf.data);
pclose(f);
/*输出结果
open:a.out
client
client.c
cs.c
ser
ser.h
server.c
*/
功能:执行shell可以获取输出结果,用fread读取结果,可以直接printf输出,也可以写入文件中。屏幕上不会直接打印出来
参数1:命令
参数2:r或w,一般要r
2.4改变当前目录chdir
int chdir(const char *path);
参数:指向目录的指针
2.5字符串分割strtok
char *strtok(char *str, const char *delim);
/*用法例子*/
char a[128]="xiao wei !!!";
//char *a = "xiao wei !!!";
char *p;
printf("a = %s\n",a);
p = strtok(a," ");
printf("p1 = %s\n",p);
printf("a = %s\n",a);
p = strtok(NULL," ");
printf("p2 = %s\n",p);
printf("a = %s\n",a);
p = strtok(NULL," ");
printf("p3 = %s\n",p);
printf("a = %s\n",a);
p = strtok(NULL," ")
printf("p4 = %s\n",p);
printf("a = %s\n",a);
return 0;
/*输出结果
a = xiao wei !!!
p1 = xiao
a = xiao
p2 = wei
a = xiao
p3 = !!!
a = xiao
p4 = (null)
a = xiao
*/
用法:
第一次调用参数1为字符串str(只能是数组a[],不能是指针类型char*a)
第二次参数1为NULL
原理:
第一次调用把字符串中分割符替换成’\0’,返回字符串地址
第二次跳过字符串的第一个\0,返回\0后面的字符串地址
最终原字符串已经被破坏,输出字符串只会输出第一个返回的字符串
参数1:要分割的字符串
参数2:分割符
2.6字符串比较strncmp
int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t n);
/*例子*/
if(!strncmp("ls",buf,2)) return LS;
返回值:一样返回0,不一样非0
参数1:比较字符串1
参数2:比较字符串2
参数3:比较前几个是否一样
注:为什么不用strcmp,因为strcmp有时候会出错
3、实现思路
服务器
1.创建socket,等待客户端连接
2.有连接fork一个进程,服务器继续等待连接
3.fork的进程read等待信息,做出相应命令
4.read到quit结束进程
客户端
1.socket连接服务器
2.连接成功fork进程,父进程wait等待,子进程gets输入
3.子进程gets输入后传命令到服务器
4.gets到quit退出进程
上传,下载补充
1.做个char* p指针
2.用sleek计算出文件大小
3.malloc给p指针分配内存
4.把内容读到p
5.给服务器/客户端发2次内容,个数和文件内存
6.服务器/客户端malloc分配内存,接收文件内容,然后放到新创建文件
4、代码展示
头文件
#define LS 0
#define LLS 1
#define PWD 2
#define CD 3
#define RM 5
#define GET 6
#define PUT 7
#define LPWD 8
#define LCD 9
#define LRM 10
#define QUIT 120
struct Mcc
{
int set;
int type;
char cmd[128];
char data[1024];
};
服务器
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "ser.h"
#include <sys/stat.h>
#include <fcntl.h>
void serv_client(int c_fd)
{
int set;
int fd;
struct Mcc buf;
char *p;
while(1)
{
memset(&buf,0,sizeof(buf));
read(c_fd,&buf,sizeof(buf));
printf("cmd:%s\n",buf.cmd);
switch(buf.set)
{
case QUIT:
exit(0);
case GET:
if(access(buf.cmd,F_OK) == -1)
{
printf("type:%d\n",buf.type);
strcpy(buf.data,"NO This file!!!");
write(c_fd,&buf,sizeof(buf));
}
else
{
fd = open(buf.cmd,O_RDWR);
read(fd,buf.data,1024);
write(c_fd,&buf,sizeof(buf));
close(fd);
}
break;
case PUT:
fd = open(buf.cmd,O_RDWR|O_CREAT,0600);
write(fd,buf.data,1024);
close(fd);
break;
case PWD:
case LS:
{
FILE *f = popen(buf.cmd,"r");
fread(buf.data,1024,1,f);
write(c_fd,&buf,sizeof(buf));
pclose(f);
break;
}
case RM:
system(buf.cmd);
strcpy(buf.data,"success......\n");
write(c_fd,&buf,sizeof(buf));
break;
case CD:
chdir(buf.cmd);
strcpy(buf.data,"success......\n");
write(c_fd,&buf,sizeof(buf));
break;
case 100:
printf("error,Reenter!!!\n");
break;
}
}
}
int main(int argc,char **argv)
{
if(argc != 3)
{
printf("usage: command listen_port\n");
exit(-1);
}
int jieshou;
int fid;
int s_fd;
int c_fd;
struct sockaddr_in addr;
struct sockaddr_in c_addr;
memset(&c_addr,0,sizeof(struct sockaddr_in));
memset(&addr,0,sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&addr.sin_addr);
s_fd = socket(AF_INET,SOCK_STREAM,0);
if(s_fd < 0)
{
perror("socket");
exit(-1);
}
if(bind(s_fd,(struct sockaddr *)&addr,sizeof(struct sockaddr_in)) < 0)
{
perror("bind");
exit(-1);
}
if(listen(s_fd,10) < 0)
{
perror("listen");
exit(-1);
}
jieshou = sizeof(struct sockaddr_in);
while(1)
{
c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&jieshou);
if(c_fd < 0)
{
perror("accept");
exit(-1);
}
else
{
printf("client IP:%s\n",inet_ntoa(c_addr.sin_addr));
}
fid = fork();
if(fid < 0)
{
perror("fork error!");
exit(-1);
}
if(fid == 0)
{
serv_client(c_fd);
}
close(c_fd);
}
return 0;
}
客户端
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "ser.h"
char *S_tok(char *a)
{
char *p;
p = strtok(a," ");
p = strtok(NULL," ");
return p;
}
int get_cmd_type(char *buf)
{
if(!strncmp("ls",buf,2)) return LS;
if(!strncmp("lls",buf,3)) return LLS;
if(!strncmp("quit",buf,4)) return QUIT;
if(!strncmp("pwd",buf,3)) return PWD;
if(!strncmp("lpwd",buf,4)) return LPWD;
if(!strncmp("cd",buf,2)) return CD;
if(!strncmp("lcd",buf,3)) return LCD;
if(!strncmp("rm",buf,2)) return RM;
if(!strncmp("lrm",buf,3)) return LRM;
if(!strncmp("get",buf,3)) return GET;
if(!strncmp("put",buf,3)) return PUT;
return 100;
}
void serv_client(int c_fd)
{
int fd;
struct Mcc buf;
char *p;
printf(">>ls,cd,rm,pwd,lls,lcd,lrm,lpwd,quit,get,put<<\n");
while(1)
{
printf("------------------------------------------------\n");
memset(&buf,0,sizeof(buf));
printf(">");
gets(buf.cmd);
buf.set = get_cmd_type(buf.cmd);
switch(buf.set)
{
case QUIT:
write(c_fd,&buf,sizeof(buf));
exit(0);
case PWD:
case LS:
write(c_fd,&buf,sizeof(buf));
read(c_fd,&buf,sizeof(buf));
printf("%s",buf.data);
break;
case CD:
p = S_tok(buf.cmd);
strcpy(buf.cmd,p);
write(c_fd,&buf,sizeof(buf));
read(c_fd,&buf,sizeof(buf));
printf("%s",buf.data);
break;
case RM:
write(c_fd,&buf,sizeof(buf));
read(c_fd,&buf,sizeof(buf));
printf("%s",buf.data);
break;
case GET:
p = S_tok(buf.cmd);
strcpy(buf.cmd,p);
write(c_fd,&buf,sizeof(buf));
read(c_fd,&buf,sizeof(buf));
if(buf.type != -1)
{
fd = open(buf.cmd,O_RDWR|O_CREAT,0600);
write(fd,buf.data,1024);
close(fd);
}
else
{
printf("%s\n",buf.data);
}
break;
case PUT:
p = S_tok(buf.cmd);
strcpy(buf.cmd,p);
if(access(buf.cmd,F_OK) == -1)
{
printf("NO This file!!!\n");
}
else
{
fd = open(buf.cmd,O_RDWR);
read(fd,buf.data,1024);
write(c_fd,&buf,sizeof(buf));
close(fd);
}
break;
case LPWD:
case LLS:
case LRM:
p = buf.cmd;
p++;
system(p);
break;
case LCD:
p = S_tok(buf.cmd);
strcpy(buf.cmd,p);
chdir(buf.cmd);
printf("success......\n");
break;
case 100:
printf("error reenter!!!\n");
break;
}
}
}
int main(int argc,char **argv)
{
if(argc != 3)
{
printf("usage: command listen_port\n");
exit(-1);
}
int fid;
int s_fd;
struct sockaddr_in addr;
memset(&addr,0,sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&addr.sin_addr);
s_fd = socket(AF_INET,SOCK_STREAM,0);
if(s_fd < 0)
{
perror("socket");
exit(-1);
}
if(connect(s_fd,(struct sockaddr *)&addr,sizeof(struct sockaddr_in)) == -1)
{
perror("connect");
exit(-1);
}
printf("client......\n");
fid = fork();
if(fid < 0)
{
perror("fork error!");
exit(-1);
}
if(fid == 0)
{
serv_client(s_fd);
exit(0);
}
wait(NULL);
close(s_fd);
return 0;
}
师承上官可编程 —— 陈立臣