服务端server.c
#include<stdio.h>
#include<string.h>
#include<sys/types.h> /* See NOTES */
#include<sys/socket.h>
#include<stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "config.h"
#include <sys/stat.h>
#include <fcntl.h>
int option_cmd(char *cmd)
{
if ( ! (strcmp("ls",cmd)) )
return LS;
if ( ! (strcmp("pwd",cmd)) )
return PWD;
if ( ! (strcmp("quit",cmd)) )
return QUIT;
if ( strstr(cmd,"cd") != NULL )
return CD;
if ( strstr(cmd,"get") != NULL ) // 得到完成命令 如:get config.h
return GET;
if ( strstr(cmd,"put") != NULL )
return PUT;
}
char *GetDir(char *dircmd)
{
char *p;
p = strtok(dircmd," "); // 以空格为分割标志,分割指令字符串
p = strtok(NULL," "); // 以NULL为标记
return p;
}
void message_handle(struct Message msg,int fd)
{
char cmdbuf[1024] = {0};
char *file = NULL;
int file_fd;
printf("Come from Client cmd is : %s\n",msg.data); // 来自客户端的指令
int cmd = option_cmd(msg.data); // 把客户端的指令进行筛选分类
switch(cmd)
{
case LS:
case PWD:
msg.type = 0;
FILE *p = popen(msg.data,"r"); // 把 ls,pwd 命令打开读取数据,并打开内容
fread(msg.data,sizeof(msg.data),1,p); //把文件指针 p 中数据读取到msg.data中
write(fd,&msg,sizeof(msg)); // 发送数据到客户端进行显示
break;
case QUIT:
printf("The Client die out!\n"); // 结束本次连接
printf("-------------------------\n");
exit(-1);
case CD:
msg.type = 1; // 标记
char *dir = GetDir(msg.data); // 分割命令字符串
printf("The dir is : %s\n",dir); // 把这个命令打印出来
chdir(dir); // chdir函数直接执行分割出来的指令 如:../
break;
case PUT:
file_fd = open(GetDir(msg.data),O_CREAT|O_RDWR,0666);
write(file_fd,msg.msgbuf,strlen(msg.msgbuf));
close(file_fd);
break;
case GET:
file = GetDir(msg.data); // 对指令进行字符串分割处理
if(access(file,F_OK) == -1) // 判断是否有这个文件,失败返回-1
{
strcpy(msg.data,"Sorry,The file no have");
write(fd,&msg,sizeof(msg)); //把数据发送到客户端
}
else
{
msg.type = DOFILE; //标记方便客户端使用
file_fd = open(file,O_RDWR); // 用读取到的指令,打开一个新文件描述符
read(file_fd,cmdbuf,sizeof(cmdbuf)); // 把这个文件指令的数据进行读入数组
close(file_fd); // 关闭文件
strcpy(msg.data,cmdbuf); // 把数组的内容拷贝到结构体数据 data 数组中
write(fd,&msg,sizeof(msg)); // 把数据内容发送到客户端中
}
break;
}
}
int main(int argc, char **argv)
{
int s_fd; // 服务端套接字对象
int c_fd; // 客户端套接字对象
int nread; // 存放读取数据的大小
struct Message msg; // 创建Message结构体对象
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));
// 1.socket
s_fd = socket(AF_INET,SOCK_STREAM,0); // 创建服务端套接字对象
if(s_fd == -1) // 检查创建对象是否成功
{
printf("create socket failed!\n");
perror("why:");
exit(-1);
}
// 2.bind
// struct sockaddr_in
// {
// sa_family_t sin_family; /* 协议族 */
// in_port_t sin_port; /* 端口号 */
// struct in_addr sin_addr; /* IP地址结构体*/
// unisgned char sin_zero[8]; // 填充没实际意义,只为了和sockaddr结构体在内存中对齐,这样两者可相互转换
// };
// IP地址结构体需要指向 in_addr中按网络字节顺序排列的地址
// struct in_addr
// {
// uint32_t s_addr; /* address in network byte order */
// };
s_addr.sin_family = AF_INET; // 将 socket 对象和ip地址、端口进行绑定
s_addr.sin_port = htons(atoi(argv[2])); // 把端口字符串形式转换成整型
inet_aton(argv[1],&s_addr.sin_addr);
// 绑定 IP地址和端口号,对象s_addr需要强制转成 struct sockaddr * 型
bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
// 3.listen
listen(s_fd,10); // 监听客户端信号接入,设置最大接入的数量
// 4.accept
int len = sizeof(struct sockaddr_in);
while(1)
{
// 当客户端信号接入成功,创建一个新的已连接socket套接字描述符对象
c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&len);
if(c_fd == -1)
{
printf("accept client signal failed!\n");
perror("why error :");
exit(-1);
}
// 打印 ip 地址,把网络能识别的形式,转换成字符串输出
printf("Connect Ip address is %s\n ",inet_ntoa(c_addr.sin_addr));
if(fork() == 0) // 当接入了新的信号,才创建新的进程去跑这个客户端
{
while(1)
{
memset(msg.data,0,sizeof(msg.data)); // 初始化接受命令数据的数据data
nread = read(c_fd,&msg,sizeof(msg)); // 读取来自客户端的命令数据
if( nread == 0) // 客户端没有输入指令
{
printf("The Client no scanf data\n");
break;
}
else if( nread == -1) // 接受客户端指令失败
{
printf("read Client data failed\n");
exit(-1);
}
else if( nread > 0) // 接受客户端指令成功
{
message_handle(msg,c_fd); // 发送到数据处理函数,进行分类处理
}
}
}
}
close(s_fd);
close(c_fd);
return 0;
}
客户端client.c
#include<stdio.h>
#include <unistd.h>
#include<string.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "config.h"
int option_cmd(char *cmd)
{
if( !(strcmp("ls",cmd)) )
return LS;
if( !(strcmp("pwd",cmd)) )
return PWD;
if( !(strcmp("lls",cmd)) )
return LLS;
if( !(strcmp("quit",cmd)) )
return QUIT;
if( strstr(cmd,"get") )
return GET;
if( strstr(cmd,"put") )
return PUT;
if( !(strcmp("cd",cmd)) )
return CD;
// if( !(strcmp("lcd",cmd)) )
// return LCD;
if( strstr(cmd,"lcd"))
return LCD;
return -1;
}
char *GetDir(char *cmd)
{
char *p;
p = strtok(cmd," ");
p = strtok(NULL," ");
if( p == NULL)
{
return cmd;
}
return p;
}
int option_cmd_handle(struct Message msg,int fd)
{
char *dir = NULL; // 用于分割字符
char buf[128] = {'\0'}; // 存放msg.data中的命令
char cmdbuf[1024]; // 存放put 文件
int CMD; // 用于命令分配返回
int file_fd; // 用于存放得到的文件
strcpy(buf,msg.data); // 把输入的命令存放到buf, 主要用于 put、 lcd
dir = GetDir(buf); // 把指令进行字符串分割
CMD = option_cmd(buf); // 命令分类
switch(CMD)
{
case LS:
case PWD:
msg.type = 0; // 和服务端一样的标记
write(fd,&msg,sizeof(msg)); // 发送数据到socket对象c_fd
break;
case CD:
msg.type = 1;
write(fd,&msg,sizeof(msg));
break;
case LCD:
// dir = GetDir(buf); // 分割命令字符串
chdir(dir); // 直接打开分割后的命令
break;
case QUIT:
strcpy(msg.data,"quit"); // 拷贝终止命令,终止连接
write(fd,&msg,sizeof(msg)); // 发送数据
close(fd); // 关闭连接
exit(-1);
case LLS:
system("ls"); // 直接用system打开指令ls
break;
case GET:
write(fd,&msg,sizeof(msg));
break;
case PUT:
strcpy(cmdbuf,msg.data);
// dir = GetDir(cmdbuf); // 分割字符串命令
if(access(dir,F_OK) == -1) // 查看是否有这个文件
{
printf("The %s file is no have\n",dir);
}
else
{
file_fd = open(dir,O_RDWR); // 打开新文件
read(file_fd,msg.msgbuf,sizeof(msg.msgbuf)); //读入数据到新文件
close(file_fd); // 关闭文件
write(fd,&msg,sizeof(msg)); //发送数据到服务端获取该文件
}
break;
}
return CMD;
}
void message_handle(struct Message msg,int fd)
{
int nread;
int newfile_fd;
struct Message Msg;
nread = read(fd,&Msg,sizeof(Msg));
if(nread == 0) // 判断是否连接好服务端信号
{
printf("The server die out ! \n");
exit(-1);
}
else if(Msg.type == DOFILE)
{
char *file = GetDir(msg.data);
newfile_fd = open(file,O_RDWR|O_CREAT|0600);
write(newfile_fd,Msg.data,strlen(Msg.data));
printf("--------->");
fflush(stdout);
}
else
{
printf("---------------------------------\n");
printf("\n%s\n",Msg.data); //打印命令执行情况
printf("---------------------------------\n");
fflush(stdout);
}
}
int main(int argc, char **argv)
{
int c_fd;
int n_read;
struct Message msg;
// 1.socket
c_fd = socket(AF_INET,SOCK_STREAM,0); // 创建客户端socket对象
if(c_fd == -1) // 判断是否创建socket 对象失败,失败返回 -1
{
printf("Create socket failed\n");
exit(-1);
}
struct sockaddr_in c_addr;
memset(&c_addr,0,sizeof(struct sockaddr_in));
c_addr.sin_family = AF_INET; // 设置ip协议
c_addr.sin_port = htons(atoi(argv[2])); // 把argv[2]端口号字符串形式转为整型
inet_aton(argv[1],&c_addr.sin_addr); // 把 argv[1]的ip地址转换成网络能识别的形式
// 2. connect
// 连接服务端信号,连接成功返回 0
if( connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr)) == -1)
{
printf("Connect Server port failed\n");
exit(-1);
}
else
{
printf("Connect Server OK !\n"); // 连接成功
}
while(1)
{
memset(msg.data,0,sizeof(msg.data)); // 初始化结构体存放命令数组
gets(msg.data); // 客户输入命令
printf("You scanf cmd is : %s\n ",msg.data); // 打印客户输入的命令
int cmd = option_cmd_handle(msg,c_fd); // 把命令进行分类处理
if(cmd > IFGO) // 指 LLS 、LCD、 QUIT 、PUT 命令
{
printf("------------------->");
fflush(stdout);
continue;
}
if( cmd == -1) // 命令输入错误,没有这个命令
{
printf("The cmd is no have\n");
fflush(stdout);
continue;
}
// 分类成功,发送命令,进行命令内容打印
message_handle(msg,c_fd);
}
return 0;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/68461.html