能力要求:
1.要求熟练掌握c语言编程
2.熟练运用linux系统编程
基本思路,在socket编程的框架上,加入对命令的处理之后进行文件的读取,创建,程序调用等;
问题1:如何处理指令?
写一个函数调用字符串 相等,分割等方法。
再返回相对应值给switch进行不同指令的处理。
问题2:如何保存命令行处理结果?
采用结构体,将指令存在msg.command内,处理结果保存在msg.data内。
在调用open read 等 将读取到的文件存放 到data中。
遇到的问题
1.终止的指令应该要用Ctrl C 不能用Ctrl Z 不然端口会费掉
2.要对msg结构体memset 不然会一直保留旧的data
3.char *file int fd FILE *file 用处要分清不然连bug都看不懂
4。在getfile进行类似cd a.c 这种指令的操作时,如何保留我原来的command不被改变。
5.要多次写demo备份,不然会前功尽弃。导致之前的代码功能报废,严重甚至连之前的代码思路都被打断。
6.char *a char b[10] 怎么把command的保存住不被改变, 指针不要成为野指针 要malloc
7结构体定义 struct Msg msg
8。popen system 区别
9对get put 命令处理时的 文件读取 msg.data的先后顺序
ftp的服务器代码实现。
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define LS 1
#define PWD 2
#define GET 4
#define PUT 5
#define CD 3
#define QUIT 6
struct Msg
{
int type;
char command[2048];
char data[2048];// read readbuf
}msg;
int getType(char *cmd)
{
if(!strcmp("ls",cmd)) return LS;
if(!strcmp("pwd",cmd)) return PWD;
if(strstr(cmd,"cd")) return CD;
if(strstr(cmd,"get")) return GET;
if(strstr(cmd,"put")) return PUT;
if(!strcmp("quit",cmd)) return QUIT;
return -1;
}
char *getfile(char *str)
{
char *p;
p = strtok(str, " ");
p = strtok(NULL, " ");
return p;
}
void handle_msg(struct Msg msg,int c_fd)
{ printf(".......................................\n");
// char *file = getfile(&msg.data);
int type = getType(msg.command);
// printf("you input command is : %s",msg.command);
switch(type)
{
case LS:
case PWD:{
FILE * file = popen(msg.command,"r");
memset(msg.data,0,sizeof(msg.data));
fread(msg.data,sizeof(char),2048,file);
write(c_fd,&msg,sizeof(msg));
printf("%s",msg.data);
break;
}
case CD:{
char *dir = getfile(msg.command);
printf("dir: %s \n",dir);
chdir(dir);
break;}
case GET:{
char tmp[2048] ;
strcpy(tmp,msg.command);
char *file = getfile(msg.command);
if(access(file,0) == -1){
printf("file not exist\n");
}else if(access(file,0) == 0){
int fd =open(file,O_RDWR);
// memset(msg.data,0,sizeof(msg.data));
read(fd,msg.data,sizeof(msg.data));
// strcpy(msg.command,tmp);
strcpy(msg.command,tmp);
write(c_fd,&msg,sizeof(msg));
printf("cmd:%s \n data:%s \n",msg.command,msg.data);
printf("get file successed\n");
break;}}
case PUT:{
printf("puting------------------------");
printf("command:%s \n data: %s \n",msg.command,msg.data);
char *file = getfile(msg.command);
int fd = open(file,O_RDWR|O_CREAT,0600);
write(fd,msg.data,sizeof(msg.data));
printf("command:%s \n data: %s \n",msg.command,msg.data);
printf("put file over!\n");
break;}
case 6:{
break;}
default:
printf("your input is error ");
break;
}
}
int main(int argc, char ** argv)
{
int s_fd;
int c_fd;
int nread;
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
struct Msg msg;
memset(&s_fd,0,sizeof(struct sockaddr_in));
memset(&c_fd,0,sizeof(struct sockaddr_in));
//1.socket 创建socket
s_fd = socket( AF_INET ,SOCK_STREAM,0);
//sever send message
if(s_fd == -1){
perror("error");
exit(-1);
}
// int socket(int domain, int type, int protocol);
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&s_addr.sin_addr);
printf("create socket successed \n");
//2.bind 绑定
//int bind(int sockfd, const struct sockaddr *addr,
// socklen_t addrlen);
bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in ));
printf("bind successed \n");
//3.listen
// int listen(int sockfd, int backlog);
listen(s_fd,10);
printf("listen ok\n");
//4.accept
// int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
// client accept message
int clen = sizeof(struct sockaddr_in);
//5.read
c_fd = accept(s_fd,(struct sockaddr *)&s_addr,&clen);
if(c_fd == -1){
perror("accept");
}
while(1){
printf("get connect %s\n",inet_ntoa(c_addr.sin_addr));
//调用线程实现双方同步聊天,用read write交流
if(fork()==0){
while(1){
//6.write
memset(&msg,0,sizeof(msg));//每次初始化缓存,防止内容重复
printf(">");
gets(msg.command);
write(c_fd,&msg,sizeof(msg));
}
}
while(1){
memset(&msg,0,sizeof(msg)); //
nread = read(c_fd,&msg,sizeof(msg));
if(nread == 0){
perror("read");
sleep(3);
}else {
printf("your command :%s\n",msg.command);
handle_msg(msg,c_fd);
}
}
}
// close(s_fd);
// close(c_fd);
return 0;
}
客户端的代码实现
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define LS 1
#define PWD 2
#define GET 4
#define PUT 5
#define CD 3
#define QUIT 6
#define LLS 7
#define LCD 8
#define WRONG -1
struct Msg
{
int type;
char command[2048];
char data[2048];// read readbuf
}msg;
getType(char *cmd)
{
if(!strcmp("ls",cmd)) return LS;
if(!strcmp("pwd",cmd)) return PWD;
if(strstr(cmd,"cd")) return CD;
if(strstr(cmd,"get")) return GET;
if(strstr(cmd,"put")) return PUT;
if(!strcmp("quit",cmd)) return QUIT;
if(!strcmp("lls",cmd)) return LLS;
if(!strcmp("lcd",cmd)) return LCD;
return -1;
}
char *getfile(char *str)
{
char *p;
p = strtok(str, " ");
p = strtok(NULL, " ");
return p;
}
handle_msg(struct Msg msg,int c_fd)
{
// char *file = getfile(&msg.data);
int type = getType(msg.command);
// printf("you input command is : %s",msg.command);
printf("you type is %d \n",type);
switch(type)
{
case LS:
case PWD:
write(c_fd,&msg,sizeof(msg));
break;
case CD:{
write(c_fd,&msg,sizeof(msg));
break;}
case GET:{
write(c_fd,&msg,sizeof(msg));
break;}
case PUT:{
char tmp[2048] ;
strcpy(tmp,msg.command);
char *file = getfile(msg.command);
if(access(file,0) == -1){
printf("file not exist\n");
}else if(access(file,0) == 0){
int fd =open(file,O_RDWR);
// memset(msg.data,0,sizeof(msg.data));
read(fd,msg.data,sizeof(msg.data));
// strcpy(msg.command,tmp);
strcpy(msg.command,tmp);
write(c_fd,&msg,sizeof(msg));
printf("cmd:%s \n data:%s \n",msg.command,msg.data);
printf("put file successed\n");
break;}
}
case LLS:{
system("ls");
break;}
case LCD :
{
char *dir = getfile(msg.command);
printf("dir: %s \n",dir);
chdir(dir);
break;
}
case WRONG:
printf("your input is error ");
break;
default : break;
}
return 0;
}
read_handle_msg(struct Msg msg,int c_fd)
{
int type = getType(msg.command);
// printf("you input command is : %s",msg.command);
switch(type)
{
case LS:
case PWD:printf("-------------------------------\n");
printf("command %s\n",msg.command);
printf("\n%s\n",msg.data);
printf("-------------------------------\n");
break;
case CD:{
break;}
case GET:{
char *file = getfile(msg.command);
int fd = open(file,O_RDWR|O_CREAT,0600);
write(fd,msg.data,sizeof(msg.data));
printf("get file over!\n");
break;}
case PUT:{
break;
}
case 6:{
break;}
default:
break;
}
return 0;
}
int main(int argc, char ** argv)
{
int c_fd;
int nread;
struct sockaddr_in c_addr;
struct Msg msg;
memset(&c_fd,0,sizeof(struct sockaddr_in));
//1.socket
c_fd = socket( AF_INET ,SOCK_STREAM,0);
//sever send message
if(c_fd == -1){
perror("socket");
exit(-1);
}
// int socket(int domain, int type, int protocol);
c_addr.sin_family = AF_INET;
c_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&c_addr.sin_addr);
printf("create socket successed \n");
// int connect(int sockfd, const struct sockaddr *addr,
// socklen_t addrlen);
if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr))== -1)//客户端 直接用connect
{
perror("connect");
exit(-1);
}
while(1){
if(fork()==0){
while(1){
//6.write
memset(&msg,0,sizeof(msg));//每次初>始化缓存,防止内容重复
printf(">");
gets(msg.command);
handle_msg(msg,c_fd);
// write(c_fd,&msg,sizeof(msg));
// write(c_fd,msg.command,sizeof(msg.command));
}
}
while(1){
memset(&msg,0,sizeof(msg)); //
nread = read(c_fd,&msg,sizeof(msg));
if(nread == -1){
perror("read");
sleep(3);
}else {
// printf("your command :%s\n",msg.command);
read_handle_msg(msg,c_fd);
/* printf("-------------------------------\n");
printf("\n%s\n",msg.data);
printf("-------------------------------\n");*/
}
}
}
//6.write
printf("connect successed \n");
return 0;
}