服务端编写思路
一、自定义头文件文件config.h
①宏定义各项指令
②创建结构体
#define LS 0
#define CD 1
#define GET 2
#define PUT 3
#define PWD 4
#define FIFO 5
#define LLS 6
#define LCD 7
#define QUIT 8
struct MSG{
int type;
char cmd[1024];
char text[1024];
};
二、socket通道编程
①创建socket套接字
②绑定套接字bind
③监听listen
④接收套接字上连接accept
a.当连接成功后,打印此时IP地址
b.创建进程,创建while(1)循环,循环内每次重置输入指令,判断是否读取到指令,
若读取到指令,则调用msg_handler函数
三、msg_handeler函数
void msg_handler(struct Msg msg,int fd)
参数struct Msg msg为定义文件内的结构体
参数int fd为accept()是的返回值通配符,相当于与客户端之间的通信通道。
①定义一个int类型变量来表示获取的命令,即此时需要先转换字符串命令为整形数字
此处调用get_cmd_type()函数。
int get_cmd_type(char *cmd)
{
if(!strcmp("ls",cmd)) return LS;
if(!strcmp("quit",cmd)) return QUIT;
if(!strcmp("pwd",cmd)) return PWD;
if(strstr(cmd,"cd")!=NULL) return CD;
if(strstr(cmd,"get")!=NULL) return GET;
if(strstr(cmd,"put")!=NULL) return PUT;
}
②LS(显示当前路径下的文件)和PWD(显示当前路径)
a.利用popen,fread,write函数显示指令名称.
③CD指令(cd指令后需要跟其他字符,此时需要调用字符串分割函数)
char *getName(char *cmsg)
{
char *p;
p=strtok(cmsg,"");
p=strtok(NULL,"");
return p;
}
a.定义指针来接收文件名,并打印文件名
b.利用chidr函数来实现目录跳转
④GET(获得文件)
a.定义指针来接收文件名
b.利用access函数来判断文件是否存在.若存在则打开文件,读写文件到心得地址.
⑤PUT(上传文件)
a.定义通配符来接收打开文件
b.把数据写到结构体的数据域
c.关闭光标
⑥QUIT(关闭指令)
服务端代码
#include<stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdlib.h>
#include<string.h>
#include <sys/types.h>
#include <sys/socket.h>
//#include<linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include"config.h"
char* getName(struct MSG msg)
{
char* p;
p=strtok(msg.cmd," ");
p=strtok(NULL," ");
return p;
}
int get_cmd_type(char* cmd){
if(strcmp(cmd,"quit")==0){
return QUIT;
}
if(strcmp(cmd,"ls")==0){
return LS;
}
if(strcmp(cmd,"pwd")==0){
return PWD;
}
if(strstr(cmd,"get")!=NULL){
return GET;
}
if(strstr(cmd,"cd")!=NULL){
return CD;
}
if(strstr(cmd,"put")!=NULL){
return PUT;
}
return -1;
}
void cmd_handler(struct MSG msg,int a_fd){
int n_read;
int filefd;
int ret;
char* p=NULL;
FILE* F = NULL;
ret = get_cmd_type(msg.cmd);
switch(ret){
case LS:
msg.type=0;
F=popen(msg.cmd,"r");
n_read=fread(msg.cmd,sizeof(msg.cmd),1,F);
if(n_read ==-1){
strcpy(msg.cmd,"popen error");
write(a_fd,msg.cmd,sizeof(msg.cmd));
}
write(a_fd,&msg,sizeof(msg));
break;
case PWD:
msg.type=4;
F=popen(msg.cmd,"r");
n_read=fread(msg.cmd,sizeof(msg.cmd),1,F);
if(n_read ==-1){
strcpy(msg.cmd,"pwd error");
write(a_fd,msg.cmd,sizeof(msg.cmd));
}
write(a_fd,&msg,sizeof(msg));
break;
case CD:
msg.type=1;
p=getName(msg);
chdir(p);
break;
case QUIT:
msg.type=8;
printf("client quit\n");
exit(-1);
break;
case PUT:
p=getName(msg);
filefd=open(p,O_RDWR|O_CREAT,0666);
printf("file:%s\n",getName(msg));
write(filefd,msg.text,strlen(msg.text));
close(filefd);
break;
case GET:
p=getName(msg);
if(access(p,F_OK)!=0){
printf("file not exist\n");
msg.type=2;
break;
}
msg.type=3;
printf("file :%s\n",getName(msg));
filefd = open(p,O_RDWR);
read(filefd,msg.text,sizeof(msg.text));
write(a_fd,&msg,sizeof(msg));
close(filefd);
break;
}
}
int main(int argc,char** argv){
int s_fd; //socket
int a_fd; //accept
int n_read;
int size = sizeof(struct sockaddr_in);
struct MSG msg;
struct sockaddr_in s_addr;
struct sockaddr_in a_addr;
memset(&s_addr,0,sizeof(struct sockaddr_in));
memset(&a_addr,0,sizeof(struct sockaddr_in));
memset(&msg,0,sizeof(struct MSG));
//1.socket
s_fd = socket(AF_INET,SOCK_STREAM,0 );
if(s_fd==-1){
perror("socket");
}
//2.bind
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&(s_addr.sin_addr));
int returnid = bind(s_fd,(struct sockaddr*)&s_addr,size);
if(returnid==-1){
perror("bind");
}
//3.listen
listen(s_fd,10);
//4.accept
while(1){
a_fd=accept(s_fd,(struct sockaddr*)&a_addr,&size);
if(a_fd==-1){
perror("accept");
}
else{
printf("get connected:%s\n",inet_ntoa(a_addr.sin_addr));
}
printf("<---------------Welcome to FTP:--------->\n");
if(fork()==0){
while(1){
memset(&msg,0,sizeof(struct MSG));
n_read = read(a_fd,&msg,sizeof(msg));
if(n_read == 0){
printf("quit\n");
continue;
}
printf("client chooses the command:%s\n",msg.cmd);
cmd_handler(msg,a_fd);
}
}
}
close(s_fd);
close(a_fd);
return 0;
}
客户端编写思路
一、创建宏定义文件
①宏定义各项指令
②创建结构体
struct Msg
{
int type;
char cmd[1024]; //存放指令
char text[1024]; //存放内容
}
二、socket通道编程
①创建socket套接字
②发起连接connect
a.判断连接是否成功,若成功则打印连接
b.调用函数cmd_handler( ),对输入指令进行switch分支操作
c.不断获取用户输入命令,仅当是LS,PWD,GET时调用handler_server_message函数
三、判断指令操作cmd_handler函数
①LS,CD,PWD:显示指令
②GET:显示获得的文件
③PUT
a.将指令写在新开辟的空间中。
b.获取文件名(调用getdir函数)
c.判断文件是否存在,不存在则打印not exist,存在则进行读写操作
④LLS:直接调用system()跳转到当前
⑤LCD:调用getdir()获得文件名,再调用chdir()跳转
⑥QUIT:退出
四、handler_server_message()用来发送文件
客服端代码
#include<stdio.h>
#include <unistd.h>
#include<stdlib.h>
#include<string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
//#include<linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <time.h>
#include"ftp.h"
char* getName(struct MSG msg)
{
char* p;
p=strtok(msg.cmd," ");
p=strtok(NULL," ");
return p;
}
int get_cmd_type(char* cmd)
{
if(strcmp(cmd,"lls")==0){
return LLS;
}
if(strcmp(cmd,"quit")==0){
return QUIT;
}
if(strcmp(cmd,"ls")==0){
return LS;
}
if(strcmp(cmd,"pwd")==0){
return PWD;
}
if(strstr(cmd,"get")!=NULL){
return GET;
}
if(strstr(cmd,"cd")!=NULL){
return CD;
}
if(strstr(cmd,"put")!=NULL){
return PUT;
}
return -1;
}
void message_handler(struct MSG msg,int s_fd)
{
struct MSG mymsg;
int fd;
char* p=NULL;
read(s_fd,&mymsg,sizeof(mymsg));
if(mymsg.type == 2){
printf("this file not exist\n");
return ;
}
else if(mymsg.type==3){
p=getName(msg);
fd = open(p,O_RDWR|O_CREAT,0666);
write(fd,mymsg.text,strlen(mymsg.text));
close(fd);
}
else{
printf("\n");
printf("The thing from socket is:\n");
printf(">>>>\n%s",mymsg.cmd);
printf("<<<<\n");
}
}
int cmd_handler(struct MSG msg,int s_fd)
{
char* p=NULL;
int flag;
char readbuff[128]={0};
int type;
int returncmd=get_cmd_type(msg.cmd);
struct MSG hhmsg;
switch(returncmd){
case LS:
msg.type=0;
write(s_fd,&msg,sizeof(struct MSG));
break;
case PWD:
msg.type=4;
write(s_fd,&msg,sizeof(struct MSG));
break;
case QUIT:
msg.type=8;
write(s_fd,&msg,sizeof(struct MSG));
close(s_fd);
exit(-1);
break;
case CD:
msg.type=1;
write(s_fd,&msg,sizeof(struct MSG));
break;
case LLS:
printf(">>>>\n");
system("ls");
break;
case PUT:
hhmsg=msg;
p=getName(msg);
if(access(p,F_OK)!=0){
printf("the file not exist");
break;
}
flag=open(p,O_RDWR);
read(flag,hhmsg.text,sizeof(hhmsg.text));
write(s_fd,&hhmsg,sizeof(hhmsg));
break;
case GET:
msg.type=2;
write(s_fd,&msg,sizeof(msg));
break;
}
return returncmd;
}
int main(int argc,char** argv){
int s_fd;
int c_fd;
int ret; //judge return define type
struct MSG msg;
struct sockaddr_in s_addr;
memset(&s_addr,0,sizeof(struct sockaddr_in));
//get now time
time_t timep;
struct tm *p;
time (&timep);
p=gmtime(&timep);
//1.socket
s_fd = socket(AF_INET,SOCK_STREAM,0 );
if(s_fd==-1){
perror("socket");
}
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&(s_addr.sin_addr));
//2.connect
int size = sizeof(struct sockaddr_in);
printf(" \n");
c_fd = connect(s_fd,(struct sockaddr*)&s_addr,size);
if(c_fd== 0){
printf("<----------connect successful----------->\n");
}else{
perror("connect");
}
printf("Welcome to the FTP file receiving station\n");
//printf("%d\n",1900+p->tm_year);/*鑾峰彇褰撳墠骞翠唤,浠�1900寮€濮嬶紝鎵€浠ヨ鍔�1900*/
//printf("%d\n",1+p->tm_mon);/*鑾峰彇褰撳墠鏈堜唤,鑼冨洿鏄�0-11,鎵€浠ヨ鍔�1*/
//printf("%d\n",8+p->tm_hour);/*鑾峰彇褰撳墠鏃�,杩欓噷鑾峰彇瑗挎柟鐨勬椂闂�,鍒氬ソ鐩稿樊鍏釜灏忔椂*
//printf("%d\n",p->tm_min); /*鑾峰彇褰撳墠鍒�*/
printf("Login time %d-%d-%d:%d\n",1900+p->tm_year,1+p->tm_mon,8+p->tm_hour,p->tm_min);
while(1){
printf("........................................\n");
printf("<<************************************>>\n");
printf("Please input your command:");
printf("\n");
memset(&msg,0,sizeof(msg));
gets(msg.cmd);
ret=cmd_handler(msg,s_fd);
if(ret==-1){
printf("command not exist\n");
continue;
}
if(ret==0 || ret==2 || ret==4){
message_handler(msg,s_fd);
}
sleep(1);
}
close(s_fd);
return 0;
}