FTP传输项目

FTP传输项目

衔接Linux–网络编程,使用socke套接字实现。

此项目包含文件编程、进程、网络编程。

要点巩固:

​ Server

  1. socket():返回一个网络描述符(类似open返回文件描述符)

  2. bind() :为套接字添加信息(IP地址和端口号)

  3. listen():监听网络连接

  4. accept():监听到有客户端接入,接受一个连接

  5. write() & read():数据交互

  6. close():关闭套接字,断开连接

    Client

    1. socket()
    2. connect()
    3. write() & read()
    4. close()

一、实现客服端退出(quit)功能

fflush函数

fflush_百度百科 (baidu.com)

函数名: 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_百度百科 (baidu.com)

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_百度百科 (baidu.com)

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;
}

运行结果:

删除服务端文件:
在这里插入图片描述

删除客户端文件:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值