Linux:文件传输(2)

Linux:文件传输(2)_第1张图片
(1)ls命令执行:服务器端执行ls命令,服务器端fork复制产生子进程,在把子进程替换成ls(exec),服务器端发给客户端
(2)rm命令执行:fork客户端发给服务器端
(3)为了防止客户端和服务器端不能交互,所以当每次执行命令时候,客户端给服务器端发送"ok#…"(仅仅代表命令执行成功,不代表其他)
(4)无名管道:子进程把输出信息写入无名管道中,父进程从无名管道中把信息读出来,然后发送给客户端,客户端在打印出来。
dup方法:复制文件描述符
先创建管道,在复制一下,管道就会被自动复制到子进程中
(5)服务器端:输入客户端发送过来的命令,然后解析命令

客户端代码:

#include
#include
#include
#include
#include
#include
#include
#include
 
int conn_ser();
char*get_cmd(char buff[],char *myargv[]);
int main()
{
	int sockfd=conn_ser();
	if(sockfd==-1)
	{
	printf("connect ser failed\n");
	exit(0);
	}

	while(1)
	{
		char buff[128]={0};
		printf("connect 127.0.0.1>>");
		fflush(stdout);
		
		fgets(buff,128,stdin);
		buff[strlen(buff)-1]=0;
 
 		char send_buff[128]={0};
		strcpy(send_buff,buff);
		
		char *myargv[10]={0};//解析的命令和参数
		char*cmd=get_cmd(buff,myargv);

		if(cmd==NULL)
		{
			continue;
 		}

		if(strcmp(cmd,"end")==0)
		{
			break;
		}
		else if(strcmp(cmd,"get")==0)
		{
	        //下载
		}
		else if(strcmp(cmd,"up")==0)
		{
			//上传
		}
		else//和服务器交互的命令
		{
			send(sockfd,send_buff,strlen(send_buff),0);
			char recv_buff[1024]={0};
			int res=recv(sockfd,recv_buff,1023,0);
			if(res<=0)
			{
				printf("ser close\n");
				break;
			}
			if(strncmp(recv_buff,"ok#",3)==0)
 			{
				printf("%s\n",recv_buff+3);
			}
			else
			{
				printf("cmd run err\n");
			}
		}
	}
	close(sockfd);
}
char*get_cmd(char buff[],char *myargv[])
{
	if(buff==NULL||myargv==NULL)
	{
		return NULL;
	}
	int i=0;
	char*s=strtok(buff,"");
	while(s!=NULL)
	{
		myargv[i++]=s;
		s=strtok(NULL,"");
	}
	return myargv[0];
}
int conn_ser()
{
	int sockfd=socket(AF_INET,SOCK_STREAM,0);
	if(sockfd==-1)
	{
		return -1;
	}
	struct sockaddr_in saddr;
	memset(&saddr,0,sizeof(saddr));
	saddr.sin_family=AF_INET;
	saddr.sin_port=htons(6000);
	saddr.sin_addr.s_addr=inet_addr("127.0.0.1");
	
	int res=connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
	if(res==-1)
	{
		return -1;
	}
	return sockfd;//创建套接字失败或者链接服务器失败就会返回-1
}
               

服务器端口:

#include"work_thread.h"
#include

#define MAX_ARG 10//最大参数个数

char*get_cmd(char buff[],char*myargv[])//解析buff,并且得到buff    中执行的命令,命令一般都在第一个字段,返回第一个字段
{
	//分割字符
	if(buff==NULL)
	{
		return NULL;
 	}
	char *p=NULL;//用来定义分割字符串的位置
	int i=0;//定义给数组的第几个元素进行赋值
	char*s=strtok_r(buff," ",&p);
	while(s!=NULL)//取出字段,并且字段不为空
	{
		myargv[i++]=s;
		s=strtok_r(NULL," ",&p);
	}
	return myargv[0];
}
void*work_thread(void*arg)
{
	int c=(int)arg;
	if(c<0)
	{
		pthread_exit(NULL);
		//return;
	}
	while(1)
	{
		char buff[128]={0};//保存客户端发送过来的命令(ls rm,ge    t a.c...)
		int num=recv(c,buff,127,0);//接受套接字
		if(num<=0)//客户端关闭
		{
			break;
		}
		
		char*myargv[MAX_ARG]={0};
		char*cmd=get_cmd(buff,myargv);
		if(cmd==NULL)
		{
			send(c,"err",3,0);
 			continue;
		}

		if(strcmp(cmd,"get")==0)
		{
			//下载send_file(c);
		}
		else if(strcmp(cmd,"up")==0)
        {
			//上传recv_file();
		}
 		else//客户端要和服务器端交互
		{
			//fork+exec;
 			int pipefd[2];//pipefd[0],读端,pipefd[1],写端,父>    进程是读端,子进程是写端
 			if(pipe(pipefd)==-1)//创建管道
			{
				send(c,"err",3,0);//创建管道失败
				continue;
			}
			pid_t pid=fork();//fork产生子进程
			if(pid==-1)
			{
				send(c,"err",3,0);
				continue;
			}
			if(pid==0)
			{
				dup2(pipefd[1],1);//管道文件描述符的文件拷贝到>    屏幕,屏幕就会显示
				dup2(pipefd[1],2);//原来打印到屏幕的信息会写在>    管道里面
				close(pipefd[0]);
				execvp(cmd,myargv);
				perror("not find cmd");//当命令执行失败的时候执
    行这个
				exit(0);
			}
			close(pipefd[1]);
			wait(NULL);
			char read_pipe[1024]={"ok#"};
			read(pipefd[0],read_pipe+3,1020);
			send(c,read_pipe,strlen(read_pipe),0);
			close(pipefd[0]);
		}
	}
	close(c);
	printf("one client close\n");
}
void thread_start(int c)
{
	pthread_t id;
	pthread_create(&id,NULL,work_thread,(void*)c);
}

你可能感兴趣的:(Linux,linux)