FTP传输项目
衔接Linux–网络编程,使用socke套接字实现。
此项目包含文件编程、进程、网络编程。
要点巩固:
Server
-
socket():返回一个网络描述符(类似open返回文件描述符)
-
bind() :为套接字添加信息(IP地址和端口号)
-
listen():监听网络连接
-
accept():监听到有客户端接入,接受一个连接
-
write() & read():数据交互
-
close():关闭套接字,断开连接
Client
- socket()
- connect()
- write() & read()
- close()
一、实现客服端退出(quit)功能
fflush函数
函数名: fflush
//fflush是一个在C语言标准输入输出库中的函数,功能是冲洗流中的信息,该函数通常用于处理磁盘文件。fflush()会强迫将缓冲区内的数据写回参数stream 指定的文件中。
功 能: 清除读写缓冲区,在需要立即把输出缓冲区的数据进行物理写入时
头文件:stdio.h
原型:int fflush(FILE *stream)
其中stream是要冲洗的流
返回值:
如果成功刷新,fflush返回0。指定的流没有缓冲区或者只读打开时也返回0值。返回EOF指出一个错误。
注意:如果fflush返回EOF,数据可能由于写错误已经丢失。当设置一个重要错误处理器时,最安全的是用setvbuf函数关闭缓冲或者使用低级I/0例程,如open、close和write来代替流I/O函数。
其他用法:
fflush(stdin)刷新标准输入缓冲区,把输入缓冲区里的东西丢弃[非标准]
fflush(stdout)刷新标准输出缓冲区,把输出缓冲区里的东西打印到标准输出设备上
message.h
#define QUIT 0 // 客服端退出
struct Message
{
int type;
char cmd[128];
char data[1024];
};
sever.c
#include <stdio.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
//#include <linux/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "message.h"
int get_cmd(char *cmd)
{
if(!strcmp("quit",cmd)) return QUIT;
return -1;
}
void message_handler(struct Message message,int fd)
{
printf("cmd:%s\n",message.cmd);
int ret = get_cmd(message.cmd);
switch(ret)
{
case QUIT:
printf("client quit\n");
exit(-1);
}
}
int main(int argc,char **argv)
{
int s_fd;
int c_fd;
int c_addrlen;
int nread;
char readbuf[1024] = {0};
struct Message message;
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
if(argc != 3){
printf("please input right param\n");
exit(-1);
}
memset(&readbuf,0,sizeof(readbuf));
memset(&s_addr,0,sizeof(struct sockaddr_in));
memset(&c_addr,0,sizeof(struct sockaddr_in));
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&s_addr.sin_addr);
//1.socket
s_fd = socket(AF_INET,SOCK_STREAM,0);
if(s_fd == -1){
perror("socket");
exit(-1);
}
//2.bind
if(bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in)) == -1){
perror("bind");
exit(-1);
}
//3.listen
if(listen(s_fd,5) == -1){
perror("listen");
exit(-1);
}
//4.accept
c_addrlen = sizeof(struct sockaddr_in);
while(1){
c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&c_addrlen);
if(c_fd == -1){
perror("accept");
exit(-1);
}
printf("I get your IP :%s\n",inet_ntoa(c_addr.sin_addr));
//5.write/read
if(fork() == 0){
while(1){
memset(&readbuf,0,sizeof(readbuf));
nread = read(c_fd,&message,sizeof(message));
if(nread == -1 ){ //read失败时
perror("read");
}else if(nread == 0){ //read为空时
printf("client out\n");
break;
}else if(nread > 0){ //read有数据时
message_handler(message,c_fd);
}
}
}
}
//6.close
close(s_fd);
close(c_fd);
return 0;
}
client.c
#include <stdio.h>
#include "message.h"
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
//#include <linux/in.h>
#include <sys/types.h>
#include <sys/socket.h>
int get_cmd(char *cmd)
{
if(!strcmp("quit",cmd)) return QUIT;
return -1;
}
void server_message(struct Message message ,int fd)
{
int nread;
struct Message getMessage;
int newFileFd;
nread = read(fd,&getMessage,sizeof(getMessage));
if(nread == -1){
printf("read cmd failed!\n");
exit(-1);
}else{
printf("------------------\n");
printf("%s\n",getMessage.data);
printf("------------------\n");
printf(">>");
fflush(stdout); //清除读写缓冲区
}
}
int cmd_handler(struct Message message,int fd)
{
int ret = get_cmd(message.cmd);
switch(ret)
{
case QUIT:
write(fd,&message,sizeof(message));
exit(-1);
}
return ret;
}
int main(int argc,char **argv)
{
int c_fd;
int c_addrlen;
int nread;
struct Message message;
struct sockaddr_in c_addr;
if(argc != 3){
printf("please input right param\n");
exit(-1);
}
memset(&c_addr,0,sizeof(struct sockaddr_in));
c_addr.sin_family = AF_INET;
c_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&c_addr.sin_addr);
//1.socket
c_fd = socket(AF_INET,SOCK_STREAM,0);
if(c_fd == -1){
perror("socket");
exit(-1);
}
//2.connect
if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr_in)) == -1){ //连接服务器
perror("connect");
exit(-1);
}
printf("wait connect...\n");
//3.write/read
while(1){
memset(&message.cmd,0,sizeof(sendmess.cmd));
printf(">>");
gets(message.cmd); //获取命令
int ret = cmd_handler(message,c_fd);
if(ret == -1){
printf("please input right cmd\n");
printf(">>");
fflush(stdout); //清除读写缓冲区
continue;
}
server_message(message,c_fd);
}
//4.close
close(c_fd);
return 0;
}
运行结果:
二、实现服务端ls、pwd,客户端ls
message.h
#define LS 0 //查看服务器文件
#define CD 1 //进入服务器目录
#define PWD 2 //查看服务器文件路径
#define IFGO 3
#define LLS 4 //查看客户端文件
#define QUIT 5 //客服端退出
struct Message
{
int type;
char cmd[128];
char data[1024];
};
server.c
#include <stdio.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
//#include <linux/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "message.h"
int get_cmd(char *cmd)
{
if(!strcmp("ls",cmd)) return LS;
if(!strcmp("pwd",cmd)) return PWD;
if(!strcmp("quit",cmd)) return QUIT;
return -1;
}
void message_handler(struct Message message,int fd)
{
char data[1024] = {0};
char *file = NULL;
int fdfile;
printf("cmd:%s\n",message.cmd);
int ret = get_cmd(message.cmd);
switch(ret)
{
case LS: //查看服务器文件
case PWD: //查看服务器文件路径
message.type = 0;
FILE *r = popen(message.cmd,"r"); //Linux系统编程--进程 13.popen函数有讲
fread(message.data,sizeof(message.data),1,r); //将r内容读到message.data
write(fd,&message,sizeof(message)); //将整个结构体发给客服端
break;
case QUIT:
printf("client quit\n");
exit(-1);
}
}
int main(int argc,char **argv)
{
int s_fd;
int c_fd;
int c_addrlen;
int nread;
char readbuf[1024] = {0};
struct Message message;
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
if(argc != 3){
printf("please input right param\n");
exit(-1);
}
memset(&readbuf,0,sizeof(readbuf));
memset(&s_addr,0,sizeof(struct sockaddr_in));
memset(&c_addr,0,sizeof(struct sockaddr_in));
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&s_addr.sin_addr);
//1.socket
s_fd = socket(AF_INET,SOCK_STREAM,0);
if(s_fd == -1){
perror("socket");
exit(-1);
}
//2.bind
if(bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in)) == -1){
perror("bind");
exit(-1);
}
//3.listen
if(listen(s_fd,5) == -1){
perror("listen");
exit(-1);
}
//4.accept
c_addrlen = sizeof(struct sockaddr_in);
while(1){
c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&c_addrlen);
if(c_fd == -1){
perror("accept");
exit(-1);
}
printf("I get your IP :%s\n",inet_ntoa(c_addr.sin_addr));
//5.write/read
if(fork() == 0){ //有新接入时不断创建子进程
while(1){
memset(&readbuf,0,sizeof(readbuf));
nread = read(c_fd,&message,sizeof(message));
if(nread == -1 ){
perror("read");
}else if(nread == 0){
printf("client out\n");
break;
}else if(nread > 0){
message_handler(message,c_fd);
}
}
}
}
//6.close
close(s_fd);
close(c_fd);
return 0;
}
client.c
#include <stdio.h>
#include "message.h"
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
//#include <linux/in.h>
#include <sys/types.h>
#include <sys/socket.h>
int get_cmd(char *cmd)
{
if(!strcmp("ls",cmd)) return LS;
if(!strcmp("lls",cmd)) return LLS;
if(!strcmp("pwd",cmd)) return PWD;
if(!strcmp("quit",cmd)) return QUIT;
return -1;
}
void server_message(struct Message message ,int fd)
{
int nread;
struct Message getMessage;
int newFileFd;
nread = read(fd,&getMessage,sizeof(getMessage));
if(nread == -1){
printf("read cmd failed!\n");
exit(-1);
}else{
printf("------------------\n");
printf("%s\n",getMessage.data);
printf("------------------\n");
printf(">>");
fflush(stdout);
}
}
int cmd_handler(struct Message message,int fd)
{
int ret = get_cmd(message.cmd);
switch(ret)
{
case LS: //查看服务端文件
case PWD: //查看服务端路径
message.type = 0;
write(fd,&message,sizeof(message));
break;
case LLS: //查看客户端文件
system("ls");
break;
case QUIT: //客户端退出
write(fd,&message,sizeof(message));
exit(-1);
break;
}
return ret;
}
int main(int argc,char **argv)
{
int c_fd;
int c_addrlen;
int nread;
int mark = 0;
struct Message message;
struct sockaddr_in c_addr;
if(argc != 3){
printf("please input right param\n");
exit(-1);
}
memset(&c_addr,0,sizeof(struct sockaddr_in));
c_addr.sin_family = AF_INET;
c_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&c_addr.sin_addr);
//1.socket
c_fd = socket(AF_INET,SOCK_STREAM,0);
if(c_fd == -1){
perror("socket");
exit(-1);
}
//2.connect
if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr_in)) == -1){
perror("connect");
exit(-1);
}
printf("wait connect...\n");
//3.write/read
while(1){
memset(&message.cmd,0,sizeof(message.cmd));
if(mark == 0) printf(">>");
gets(message.cmd); //等待用户输入命令
int ret = cmd_handler(message,c_fd);
if(strlen(message.cmd) == 0){
if(mark == 1){
printf(">>");
}
continue;
}
mark = 1;
if(ret > IFGO){
printf(">>");
fflush(stdout);
continue;
}
if(ret == -1){
printf("please input right cmd\n");
printf(">>");
fflush(stdout);
continue;
}
server_message(message,c_fd);
}
//4.close
close(c_fd);
return 0;
}
运行结果:
三、实现服务端、客户端cd操作
不能使用system("cd")
来操作,system内核源码是通过fork函数来实现的,在此不实用
使用chdir函数实现cd操作
chdir函数
chdir 是C语言中的一个系统调用函数(同cd),用于改变当前工作目录,其参数为Path 目标目录,可以是绝对目录或相对目录。
chdir函数原型
#include <unistd.h>
int chdir(const char *path);
chdir_demo.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
system("pwd");
chdir("..");//返回上一级目录
system("pwd");
return 0;
return 0;
}
输出结果:
getcwd函数
getcwd()会将当前工作目录的绝对路径复制到参数buffer所指的内存空间中,参数maxlen为buffer的空间大小。
功能:获取当前工作目录
#include <unistd.h>
char *getcwd( char *buffer, int maxlen );
/*
参数说明:getcwd()会将当前工作目录的绝对路径复制到参数buffer所指的内存空间中,参数maxlen为buffer的空间大小。
返 回 值:成功则返回当前工作目录,失败返回 FALSE。
*/
getcwd_demo.c
#include <stdio.h>
#include <unistd.h>
int main()
{
char temp[4096] = {0};
getcwd(temp, sizeof(temp));//获得当前工作目录的绝对路径,存放到temp当中
printf("%s\n",temp);//输出当前绝对路径
printf("================================\n");
chdir("..");//返回上一级目录
getcwd(tmp, sizeof(temp));//获得上一级工作目录的绝对路径,存放到temp当中
printf("%s\n",temp);//输出上一级工作目录的绝对路径
return 0;
}
输出结果:
message.h
#define LS 0
#define CD 1
#define PWD 2
#define IFGO 3
#define GET 4
#define NEW 5 //客户端 cd功能
#define LLS 6
#define PUT 7
#define QUIT 8
struct Message
{
int type;
char cmd[128];
char data[1024];
};
server.c
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
//#include <linux/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "message.h"
int get_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;
return 100;
}
char *getDesDir(char *cmsg)
{
char *p;
p = strtok(cmsg," ");
p = strtok(NULL," ");
printf("%s\n",p);
return p;
}
void message_handler(struct Message message,int fd)
{
char data[1024] = {0};
char systemData[64] = ".. ~";
int ifhave6;
char *file = NULL;
int fdfile;
printf("cmd:%s\n",message.cmd);
int ret = get_cmd(message.cmd);
printf("ret :%d\n",ret);
switch(ret)
{
case LS:
case PWD:
message.type = 0;
FILE *r = popen(message.cmd,"r");
fread(message.data,sizeof(message.data),1,r);
write(fd,&message,sizeof(message));
break;
case CD:
message.type = 1;
char *dir = getDesDir(message.cmd);
chdir(dir);
getcwd(message.data,sizeof(message.data)); //获得当前目录绝对路径
write(fd,&message,sizeof(message)); //将路径发送给客户端
break;
case QUIT:
printf("client quit\n");
exit(-1);
}
}
int main(int argc,char **argv)
{
int s_fd;
int c_fd;
int c_addrlen;
int nread;
char readbuf[1024] = {0};
struct Message message;
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
if(argc != 3){
printf("please input right param\n");
exit(-1);
}
memset(&readbuf,0,sizeof(readbuf));
memset(&s_addr,0,sizeof(struct sockaddr_in));
memset(&c_addr,0,sizeof(struct sockaddr_in));
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&s_addr.sin_addr);
//1.socket
s_fd = socket(AF_INET,SOCK_STREAM,0);
if(s_fd == -1){
perror("socket");
exit(-1);
}
//2.bind
if(bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in)) == -1){
perror("bind");
exit(-1);
}
//3.listen
if(listen(s_fd,5) == -1){
perror("listen");
exit(-1);
}
//4.accept
c_addrlen = sizeof(struct sockaddr_in);
while(1){
c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&c_addrlen);
if(c_fd == -1){
perror("accept");
exit(-1);
}
printf("I get your IP :%s\n",inet_ntoa(c_addr.sin_addr));
//5.write/read
if(fork() == 0){
while(1){
memset(&readbuf,0,sizeof(readbuf));
nread = read(c_fd,&message,sizeof(message));
if(nread == -1 ){
perror("read");
}else if(nread == 0){
printf("client out\n");
break;
}else if(nread > 0){
message_handler(message,c_fd);
}
}
}
}
//6.close
close(s_fd);
close(c_fd);
return 0;
}
client.c
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "message.h"
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
//#include <linux/in.h>
#include <sys/types.h>
#include <sys/socket.h>
char *getDir(char *msg)
{
char *p;
p = strtok(msg," ");
p = strtok(NULL," ");
printf("%s\n",p);
return p;
}
int get_cmd(char *cmd)
{
if(!strcmp("ls",cmd)) return LS;
if(!strcmp("lls",cmd)) return LLS;
if(!strcmp("pwd",cmd)) return PWD;
if(!strcmp("quit",cmd)) return QUIT;
if(strstr(cmd,"cd")!=NULL) return CD;
if(strstr(cmd,"new")!=NULL) return NEW;
return -1;
}
int cmd_handler(struct Message message,int fd)
{
int fdfile;
char *dir = NULL;
char buf[32];
int ret = get_cmd(message.cmd);
switch(ret)
{
case LS:
case CD:
case PWD:
message.type = 0;
write(fd,&message,sizeof(message));
break;
case LLS:
system("ls");
break;
case NEW:
dir = getDir(message.cmd);
chdir(dir);
system("pwd");
break;
case QUIT:
write(fd,&message,sizeof(message));
exit(-1);
break;
}
return ret;
}
void server_message(struct Message message ,int c_fd)
{
int nread;
struct Message getMessage;
int newFileFd;
nread = read(c_fd,&getMessage,sizeof(getMessage));
//printf("getmessage:%d\n",getMessage.type);
if(nread == -1){
printf("read cmd failed!\n");
exit(-1);
}else if(getMessage.type == DOFILE){
char *p = getDir(getMessage.cmd);
newFileFd = open(p,O_RDWR|O_CREAT,0600);
write(newFileFd,&getMessage.data,strlen(getMessage.data));
printf(">>");
fflush(stdout);
}else {
printf("------------------\n");
printf("%s\n",getMessage.data);
printf("------------------\n");
printf(">>");
fflush(stdout);
}
}
int main(int argc,char **argv)
{
int c_fd;
int c_addrlen;
int nread;
int mark = 0;
struct Message message;
struct sockaddr_in c_addr;
if(argc != 3){
printf("please input right param\n");
exit(-1);
}
memset(&c_addr,0,sizeof(struct sockaddr_in));
c_addr.sin_family = AF_INET;
c_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&c_addr.sin_addr);
//1.socket
c_fd = socket(AF_INET,SOCK_STREAM,0);
if(c_fd == -1){
perror("socket");
exit(-1);
}
//2.connect
if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr_in)) == -1){
perror("connect");
exit(-1);
}
printf("wait connect...\n");
//3.write/read
while(1){
memset(&message.cmd,0,sizeof(message.cmd));
if(mark == 0) printf(">>");
gets(message.cmd);
if(strlen(message.cmd) == 0){
if(mark == 1){
printf(">>");
}
continue;
}
mark = 1;
int ret = cmd_handler(message,c_fd);
if(ret > IFGO){
printf(">>");
fflush(stdout);
continue;
}
if(ret == -1){
printf("please input right cmd\n");
printf(">>");
fflush(stdout);
continue;
}
//printf("inter server\n");
server_message(message,c_fd);
}
//4.close
close(c_fd);
return 0;
}
运行结果:
四、实现面对服务端上传(put)文件和获取(get)文件
message.h
#define LS 0
#define CD 1
#define PWD 2
#define GET 3
#define IFGO 4
#define NEW 5
#define LLS 6
#define PUT 7
#define QUIT 8
#define DOFILE 9
struct Message
{
int type;
char cmd[128];
char data[1024];
};
server.c
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
//#include <linux/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "message.h"
int get_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) return GET;
if(strstr(cmd,"put")!=NULL) return PUT;
return 100;
}
char *getDesDir(char *cmsg)
{
char *p;
p = strtok(cmsg," ");
p = strtok(NULL," ");
printf("%s\n",p);
return p;
}
void message_handler(struct Message message,int fd)
{
char data[1024] = {0};
char *file = NULL;
int fdfile;
printf("cmd:%s\n",message.cmd);
int ret = get_cmd(message.cmd);
switch(ret)
{
case LS:
case PWD:
message.type = 0;
FILE *r = popen(message.cmd,"r");
fread(message.data,sizeof(message.data),1,r);
write(fd,&message,sizeof(message));
break;
case CD:
message.type = 1;
printf("this is cd\n");
char *dir = getDesDir(message.cmd);
printf("dir:%s\n",dir);
chdir(dir);
getcwd(message.data,sizeof(message.data));
write(fd,&message,sizeof(message));
break;
case GET:
file = getDesDir(message.cmd);
if(access(file,F_OK) == -1){
strcpy(message.data,"no this file!");
printf("no file\n");
write(fd,&message,sizeof(message));
}else{
message.type = DOFILE;
fdfile = open(file,O_RDWR);
read(fdfile,data,sizeof(data));
close(fdfile);
strcpy(message.data,data);
write(fd,&message,sizeof(message));
}
break;
case PUT:
fdfile = open(getDesDir(message.cmd),O_RDWR|O_CREAT,0666);
write(fdfile,&message.data,strlen(message.data));
close(fdfile);
break;
case QUIT:
printf("client quit\n");
exit(-1);
}
}
int main(int argc,char **argv)
{
int s_fd;
int c_fd;
int c_addrlen;
int nread;
char readbuf[1024] = {0};
struct Message message;
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
if(argc != 3){
printf("please input right param\n");
exit(-1);
}
memset(&readbuf,0,sizeof(readbuf));
memset(&s_addr,0,sizeof(struct sockaddr_in));
memset(&c_addr,0,sizeof(struct sockaddr_in));
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&s_addr.sin_addr);
//1.socket
s_fd = socket(AF_INET,SOCK_STREAM,0);
if(s_fd == -1){
perror("socket");
exit(-1);
}
//2.bind
if(bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in)) == -1){
perror("bind");
exit(-1);
}
//3.listen
if(listen(s_fd,5) == -1){
perror("listen");
exit(-1);
}
//4.accept
c_addrlen = sizeof(struct sockaddr_in);
while(1){
c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&c_addrlen);
if(c_fd == -1){
perror("accept");
exit(-1);
}
printf("I get your IP :%s\n",inet_ntoa(c_addr.sin_addr));
//5.write/read
if(fork() == 0){
while(1){
memset(&readbuf,0,sizeof(readbuf));
nread = read(c_fd,&message,sizeof(message));
if(nread == -1 ){
perror("read");
}else if(nread == 0){
printf("client out\n");
break;
}else if(nread > 0){
message_handler(message,c_fd);
}
}
}
}
//6.close
close(s_fd);
close(c_fd);
return 0;
}
client3.c
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "message.h"
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
//#include <linux/in.h>
#include <sys/types.h>
#include <sys/socket.h>
char *getDir(char *msg)
{
char *p;
p = strtok(msg," ");
p = strtok(NULL," ");
printf("%s\n",p);
return p;
}
int get_cmd(char *cmd)
{
if(!strcmp("ls",cmd)) return LS;
if(!strcmp("lls",cmd)) return LLS;
if(!strcmp("pwd",cmd)) return PWD;
if(!strcmp("quit",cmd)) return QUIT;
if(strstr(cmd,"cd")!=NULL) return CD;
if(strstr(cmd,"new")!=NULL) return NEW;
if(strstr(cmd,"get")!=NULL) return GET;
if(strstr(cmd,"put")!=NULL) return PUT;
return -1;
}
int cmd_handler(struct Message message,int fd)
{
int fdfile;
char *dir = NULL;
char buf[32];
int ret = get_cmd(message.cmd);
switch(ret)
{
case LS:
case CD:
case PWD:
message.type = 0;
write(fd,&message,sizeof(message));
break;
case LLS:
system("ls");
break;
case NEW:
dir = getDir(message.cmd);
chdir(dir);
system("pwd");
break;
case GET:
message.type = 2;
write(fd,&message,sizeof(message));
break;
case PUT:
strcpy(buf,message.cmd);
dir = getDir(buf);
printf("cdir:%s\n",dir);
if(access(dir,F_OK) == -1){
printf("%s not exsit\n",dir);
}else{
fdfile = open(dir,O_RDWR);
memset(&message.data,0,sizeof(message.data)); //空间初始化,防止拷贝乱码
read(fdfile,message.data,sizeof(message.data));
printf("cput:%s\n",message.data);
close(fdfile);
write(fd,&message,sizeof(message));
}
break;
case QUIT:
write(fd,&message,sizeof(message));
exit(-1);
break;
}
return ret;
}
void server_message(struct Message message ,int c_fd)
{
int nread;
struct Message getMessage;
int newFileFd;
nread = read(c_fd,&getMessage,sizeof(getMessage));
printf("getmessage:%d\n",getMessage.type);
if(nread == -1){
printf("read cmd failed!\n");
exit(-1);
}else if(getMessage.type == DOFILE){
char *p = getDir(message.cmd);
newFileFd = open(p,O_RDWR|O_CREAT,0600);
write(newFileFd,&getMessage.data,strlen(getMessage.data));
printf(">>");
fflush(stdout);
}else {
printf("------------------\n");
printf("%s\n",getMessage.data);
printf("------------------\n");
printf(">>");
fflush(stdout);
}
}
int main(int argc,char **argv)
{
int c_fd;
int c_addrlen;
int nread;
int mark = 0;
struct Message message;
struct sockaddr_in c_addr;
if(argc != 3){
printf("please input right param\n");
exit(-1);
}
memset(&c_addr,0,sizeof(struct sockaddr_in));
c_addr.sin_family = AF_INET;
c_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&c_addr.sin_addr);
//1.socket
c_fd = socket(AF_INET,SOCK_STREAM,0);
if(c_fd == -1){
perror("socket");
exit(-1);
}
//2.connect
if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr_in)) == -1){
perror("connect");
exit(-1);
}
printf("wait connect...\n");
//3.write/read
while(1){
memset(&message.cmd,0,sizeof(message.cmd));
if(mark == 0) printf(">>");
gets(message.cmd);
if(strlen(message.cmd) == 0){
if(mark == 1){
printf(">>");
}
continue;
}
mark = 1;
int ret = cmd_handler(message,c_fd);
if(ret > IFGO){
printf(">>");
fflush(stdout);
continue;
}
if(ret == -1){
printf("please input right cmd\n");
printf(">>");
fflush(stdout);
continue;
}
server_message(message,c_fd);
}
//4.close
close(c_fd);
return 0;
}
运行结果:
五、实现服务端、客户端删除文件
message.h
#define LS 0 //查看客户端文件
#define CD 1 //改变服务端目录
#define PWD 2 //查看服务端目录
#define GET 3 //从服务端获得文件
#define IFGO 4 //用于判断
#define NEW 5 //改变客户端目录
#define LLS 6 //查看客户端文件
#define PUT 7 //向服务端上传文件
#define QUIT 8 //客户端退出
#define DOFILE 9 //用于get判断
#define RM 10 //删除服务端文件
#define DEL 11 //删除客户端文件
struct Message
{
int type;
char cmd[128];
char data[1024];
};
server.c
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
//#include <linux/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "message.h"
int get_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) return GET;
if(strstr(cmd,"put")!=NULL) return PUT;
if(strstr(cmd,"rm")!=NULL) return RM;
return 100;
}
char *getDesDir(char *cmsg)
{
char *p;
p = strtok(cmsg," ");
p = strtok(NULL," ");
printf("%s\n",p);
return p;
}
void message_handler(struct Message message,int fd)
{
char data[1024] = {0};
char *file = NULL;
int fdfile;
char *rmfile = NULL;
char rmFile[128] = {0};
printf("cmd:%s\n",message.cmd);
int ret = get_cmd(message.cmd);
switch(ret) //判断指令
{
case LS: //查看客户端文件
case PWD: //查看服务端目录
message.type = 0;
FILE *r = popen(message.cmd,"r");
fread(message.data,sizeof(message.data),1,r);
write(fd,&message,sizeof(message));
break;
case CD: //改变服务端目录
message.type = 1;
char *dir = getDesDir(message.cmd);
printf("dir:%s\n",dir);
chdir(dir);
getcwd(message.data,sizeof(message.data));
write(fd,&message,sizeof(message));
break;
case GET: //从服务端获得文件
file = getDesDir(message.cmd); //获得文件名
if(access(file,F_OK) == -1){ //判断是否有该文件
strcpy(message.data,"no this file!");
printf("no file\n");
write(fd,&message,sizeof(message));
}else{
message.type = DOFILE; //设置标志
fdfile = open(file,O_RDWR);
read(fdfile,data,sizeof(data)); //将文件内容读到data
close(fdfile);
strcpy(message.data,data); //拷贝data的数据给结构体
write(fd,&message,sizeof(message)); //将结构体发送给客户端
}
break;
case PUT: //向服务端上传文件
fdfile = open(getDesDir(message.cmd),O_RDWR|O_CREAT,0666); //服务端接收到指令,获得文件名,创建文件设置权限,可读可写
write(fdfile,&message.data,strlen(message.data)); //将客户端发送的结构体中的数据,写入创建的文件,实现上传
close(fdfile);
break;
case RM: //删除服务端文件
rmfile = getDesDir(message.cmd);
sprintf(rmFile,"rm %s",rmfile);
system(rmFile);
break;
case QUIT: //删除客户端文件
printf("client quit\n");
exit(-1);
}
}
int main(int argc,char **argv)
{
int s_fd;
int c_fd;
int c_addrlen;
int nread;
char readbuf[1024] = {0};
struct Message message;
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
if(argc != 3){
printf("please input right param\n");
exit(-1);
}
memset(&readbuf,0,sizeof(readbuf));
memset(&s_addr,0,sizeof(struct sockaddr_in));
memset(&c_addr,0,sizeof(struct sockaddr_in));
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&s_addr.sin_addr);
//1.socket
s_fd = socket(AF_INET,SOCK_STREAM,0);
if(s_fd == -1){
perror("socket");
exit(-1);
}
//2.bind
if(bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in)) == -1){
perror("bind");
exit(-1);
}
//3.listen
if(listen(s_fd,5) == -1){
perror("listen");
exit(-1);
}
//4.accept
c_addrlen = sizeof(struct sockaddr_in);
while(1){
c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&c_addrlen);
if(c_fd == -1){
perror("accept");
exit(-1);
}
printf("I get your IP :%s\n",inet_ntoa(c_addr.sin_addr));
//5.write/read
if(fork() == 0){
while(1){
memset(&readbuf,0,sizeof(readbuf));
nread = read(c_fd,&message,sizeof(message));
if(nread == -1 ){
perror("read");
}else if(nread == 0){
printf("client out\n");
break;
}else if(nread > 0){
message_handler(message,c_fd);
}
}
}
}
//6.close
close(s_fd);
close(c_fd);
return 0;
}
client3.c
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "message.h"
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
//#include <linux/in.h>
#include <sys/types.h>
#include <sys/socket.h>
char *getDir(char *msg) //分割指令
{
char *p;
p = strtok(msg," ");
p = strtok(NULL," ");
printf("%s\n",p);
return p;
}
int get_cmd(char *cmd) //判断指令返回指令编号
{
if(!strcmp("ls",cmd)) return LS; //查看客户端文件
if(!strcmp("lls",cmd)) return LLS; //查看客户端文件
if(!strcmp("pwd",cmd)) return PWD; //查看服务端目录
if(!strcmp("quit",cmd)) return QUIT; //客户端退出
if(strstr(cmd,"cd")!=NULL) return CD; //改变服务端目录
if(strstr(cmd,"new")!=NULL) return NEW; //改变客户端目录
if(strstr(cmd,"get")!=NULL) return GET; //改变客户端目录
if(strstr(cmd,"put")!=NULL) return PUT; //向服务端上传文件
if(strstr(cmd,"rm")!=NULL) return RM; //删除服务端文件
if(strstr(cmd,"del")!=NULL) return DEL; //删除客户端文件
return -1;
}
int cmd_handler(struct Message message,int fd)
{
int fdfile;
char *dir = NULL;
char *rmfile = NULL;
char rmFile[128] = {0};
char buf[32];
int ret = get_cmd(message.cmd); //
switch(ret) //判断指令
{
case LS:
case CD:
case PWD:
message.type = 0;
write(fd,&message,sizeof(message));
break;
case LLS:
system("ls");
break;
case NEW:
dir = getDir(message.cmd);
chdir(dir);
system("pwd");
break;
case GET:
message.type = 2;
write(fd,&message,sizeof(message));
break;
case PUT:
strcpy(buf,message.cmd);
dir = getDir(buf); //获得文件名
printf("cdir:%s\n",dir);
if(access(dir,F_OK) == -1){ //判断文件是否存在
printf("%s not exsit\n",dir);
}else{
fdfile = open(dir,O_RDWR); //打开该文件,可读可写
memset(&message.data,0,sizeof(message.data)); //读数据前先初始化空间,防止乱码
read(fdfile,message.data,sizeof(message.data)); //将文件内容读到结构体中
close(fdfile); //关闭文件防止文件损坏
write(fd,&message,sizeof(message)); //发送结构体给服务端
}
break;
case RM:
write(fd,&message,sizeof(message));
break;
case DEL:
rmfile = getDir(message.cmd);
sprintf(rmFile,"rm %s",rmfile);
system(rmFile);
break;
case QUIT:
write(fd,&message,sizeof(message));
exit(-1);
break;
}
return ret;
}
void server_message(struct Message message ,int c_fd) //接受服务端返回信息
{
int nread;
struct Message getMessage;
int newFileFd;
printf("1\n");
nread = read(c_fd,&getMessage,sizeof(getMessage));
printf("2\n");
printf("getmessage:%d\n",getMessage.type);
if(nread == -1){
printf("read cmd failed!\n");
exit(-1);
}else if(getMessage.type == DOFILE){ //用于get指令
char *p = getDir(message.cmd); //分割指令,获得文件名
newFileFd = open(p,O_RDWR|O_CREAT,0600); //创建文件名
write(newFileFd,&getMessage.data,strlen(getMessage.data)); //将服务端读取到的内容写入该文件
printf(">>");
fflush(stdout);
}else {
printf("------------------\n");
printf("%s\n",getMessage.data);
printf("------------------\n");
printf(">>");
fflush(stdout);
}
}
int main(int argc,char **argv)
{
int c_fd;
int c_addrlen;
int nread;
int mark = 0;
struct Message message;
struct sockaddr_in c_addr;
if(argc != 3){
printf("please input right param\n");
exit(-1);
}
memset(&c_addr,0,sizeof(struct sockaddr_in));
c_addr.sin_family = AF_INET;
c_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&c_addr.sin_addr);
//1.socket
c_fd = socket(AF_INET,SOCK_STREAM,0);
if(c_fd == -1){
perror("socket");
exit(-1);
}
//2.connect
if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr_in)) == -1){
perror("connect");
exit(-1);
}
printf("wait connect...\n");
//3.write/read
while(1){
memset(&message.cmd,0,sizeof(message.cmd)); //初始化指令空间
if(mark == 0) printf(">>");
gets(message.cmd);
if(strlen(message.cmd) == 0){
if(mark == 1){
printf(">>");
}
continue;
}
mark = 1;
int ret = cmd_handler(message,c_fd); //获得指令编号
if(ret > IFGO){ //用于判断指令编号
printf(">>");
fflush(stdout); //清除读写缓冲区
continue;
}
if(ret == -1){
printf("please input right cmd\n");
printf(">>");
fflush(stdout);
continue;
}
server_message(message,c_fd);
}
//4.close
close(c_fd);
return 0;
}
运行结果:
删除服务端文件:
删除客户端文件: