赞
踩
- ret_socket = socket(AF_INET,SOCK_STREAM,0);
- if(ret_socket == -1)
- {
- perror("socket");
- exit(EXIT_FAILURE);
- }
- struct sockaddr_in t0; //在前面定义结构体变量
- t0.sin_family = AF_INET;
- t0.sin_port = htons(atoi(argv[2]));
- inet_aton(argv[1],&t0.sin_addr);
-
- //通过输入的方式传参 int main(int argc ,char**argv )
- //也可以先将 atoi(argv[2]) 替换为数字,将 argv[1] 替换为ip地址
- //自己搞清楚htons atoi inet_aton这三个函数
-
- if( bind(ret_socket, (struct sockaddr*)&t0,sizeof(struct sockaddr_in) ) ==-1 )
- {
- perror("bind");
- exit(EXIT_FAILURE);
- }
- if( listen(ret_socket,10) ==-1)
- {
- perror("listen");
- exit(EXIT_FAILURE);
- }
- while(1)
- {
- ac = accept(ret_socket, (struct sockaddr*)&ac_addr, &addrlen);
- if( ac == -1)
- {
- perror("accept");
- exit(EXIT_FAILURE);
- }
-
- //父进程一直等待客户端连接,如果有客户端接入,fork一个子程序处理该客户端的连接
- fk = fork();
- if(fk == 0)
- {
- ...
-
- if(fk == 0)
- {
-
- fk2 = fork();
- if(fk2==0)//这里是第二次fork后的子进程,即子子进程
- {
- while(1)
- {
- memset(r_buf,0,sizeof(r_buf));
- recv(ac,r_buf,sizeof(r_buf),0);//不断接收客户端的消息
- if(strlen(r_buf)!=0)
- {
-
- printf("Client Message:%s\n",r_buf);
-
- }
- }
- }
- else if(fk2>0)//这里是第二次fork后的父进程 即子父进程
- {
- while(1)
- {
- memset(w_buf,0,sizeof(w_buf));
- scanf("%s",w_buf);
- getchar();
- send(ac,w_buf,strlen(w_buf),0);//不断向客户端发消息
- }
-
- }
- else //这是第二次fork失败的判断
- {
- perror("fork 2");
- exit(EXIT_FAILURE);
- }
- }
-
- else if(fk>0)//这里是第一次fork父进程
- {
-
- printf("client connection,ip=%s\n",inet_ntoa(ac_addr.sin_addr));
-
-
- }
- else //这是第一次fork失败的判断
- {
- perror("fork 1");
- exit(EXIT_FAILURE);
- }
-
- }
- int client_socket = socket(AF_INET,SOCK_STREAM,0);//第一步创建socket
- if(client_socket == -1)
- {
- perror("socket");
- exit(EXIT_FAILURE);
- }
-
-
- struct sockaddr_in client_addr;
-
- memset(&client_addr,0, sizeof(client_addr) );
-
- client_addr.sin_family = AF_INET;
-
- client_addr.sin_port = htons(atoi(argv[2]));
-
- //这里atoi(argv[2])和argv[1] 传参,和服务器一样,不清楚就替换成数字
- //搞清楚htons atoi 和main函数传参
-
- inet_aton(argv[1],&client_addr.sin_addr);
-
- int client_connect = //第二步 连接服务器 connect()函数
- connect(client_socket, (struct sockaddr*)&client_addr,sizeof(struct sockaddr_in));
-
- if(client_connect == -1)
- {
- perror("connect");
- exit(EXIT_FAILURE);
- }
- pid_t fk=fork();
- if(fk==0) //这里是客户端的子进程,不停的发消息
- {
- while(1)
- {
- memset(client_send_str,0,sizeof(client_send_str));
- //client_send_str是自定义的一个数组,存放用户输入的字符,client_send_str[1024]={0};
- scanf("%s",client_send_str);
- getchar();
- client_send = send(client_socket,client_send_str,sizeof(client_send_str),0);
- if(client_send == -1)
- {
- perror("send");
- exit(EXIT_FAILURE);
- }
- }
- else if(fk>0)//这里是客户端的父进程,不停的收消息
- {
- while(1)
- {
- memset(client_buf,0,sizeof(client_buf));
- //client_buf定义的一个数组 client_buf[1024]={0};
- client_recv = recv(client_socket,client_buf,sizeof(client_buf),0);
- if(client_recv == -1)
- {
- perror("recv");
- exit(EXIT_FAILURE);
- }
-
- if(strlen(client_buf)!=0)
- {
- printf("receive data from server:%s\n",client_buf);
- }
- }
- else
- {
- perror("fork");
- }
-
- //首先应当搞清楚strcmp字符串比较函数,两个字符串相等返回0,判断"sfile"
- //popen函数把shell命令 ls -l 的结果保存起来
- //fp应在之前声明 即FILE*fp;
- //fread将ls -l 的结果读到f_buf这个数组中,f_buf也应在之前声明 f_buf[1024]={0};
- //ac 是accept函数返回的标识符,用send函数将数据发给客户端
-
- if( strcmp(r_buf,"sfile") ==0)
- {
- memset(f_buf,0,sizeof(f_buf));
- fp = popen("ls -l","r");
- fread(f_buf,1,sizeof(f_buf),fp);
- send(ac,f_buf,sizeof(f_buf),0);
- pclose(fp);
- }
- //和获取服务器文件列表基本相同,客户端更简单一些
- //cf应在之前声明即FILE*cf
- //arr 也应在前面声明 char arr[1024]={0};
-
- if(strcmp(client_send_str,"cfile") ==0)
- {
- memset(arr,0,sizeof(arr));
- cf=popen("ls -l","r");
- fread(arr,1,sizeof(arr),cf);
- printf("########################client-files###########################\n");
- printf("%s\n",arr);
- pclose(cf);
- }
-
-
- //下面这些打印都是为了美观,可有可无
-
- if(strcmp(client_send_str,"sfile") ==0)
- {
-
- printf("########################server-files###########################\n");
-
- }
-
-
- //下面这个也是为了美观,与服务器建立连接后,先打印出来,调用background_print()可有可无
- void background_print()
- {
- char buf[64]={0};
- memset(buf,0,64);
- FILE*fp;
- fp=popen("date","r");
- fread(buf,1,64,fp);
-
- printf("####################################################\n");
- printf(" > welcome to connect server!\n");
- printf(" > sign time: %s",buf);
- printf(" > you can send or receive message,transfer files\n");
- printf(" > Enter 'sfile' to look server files\n");
- printf(" > Enter 'cfile' to look client files\n");
- printf(" > Enter 'download' to get server file\n");
- printf(" > Enter 'quit' to disconnect\n");
- printf("####################################################\n");
- //这段代码也是加在第二次fork后的子子进程
- //在前面声明char arr[100]={0};
- if( strcmp(r_buf,"quit") ==0)
- {
- printf("client quit,ip=%s\n",inet_ntoa(ac_addr.sin_addr));
- memset(arr,0,sizeof(arr));
- sprintf(arr,"kill -9 %d %d",getpid(),getppid() ); //首先搞清楚sprintf函数
- //这里用getppid()获取子父进程的pid,也是为什么要在子子进程进行收取消息的原因
- //printf("%s\n",arr);
- system(arr);
- close(ac);
- }
- else if(fk>0)
- {
-
- printf("client connection,ip=%s\n",inet_ntoa(ac_addr.sin_addr));
-
- signal(SIGCHLD, handler);
-
- //SIGCHLD信号:SIGCHLD是第17号信号.
- //子进程在终止时会向父进程发SIGCHLD信号,该信号的默认动作是忽略,
- //父进程便可以自定义SIGCHLD信号的处理函数,这样它只需专心处理自己的工作,
- //而不必关⼼子进程了, 子进程终止时会通知父进程,父进程在信号处理函数中调用waitpid清理子进程即可。
-
- }
-
-
-
- //应声明在main之前
- void handler(int sig)
- {
-
- //这段代码的作用是在循环中等待所有子进程的状态改变,当所有子进程的状态都不可用时,循环结束。
- //因为子进程可能不止一个,在同一时间可能有多个子进程结束运行所以使用while
- pid_t fw;
- while( (fw=waitpid(-1,NULL,WNOHANG)) >0 ) //先搞清楚waitpid函数,WNOHANG即非阻塞
- {
-
-
- // printf("waitpid=%d\n",fw);
-
-
- }
- //下面代码有点长,你可能受不了
- else if(strcmp(r_buf,"download") ==0)
- {
- //char p_buf[64]="Enter Filename to Download"; 使用前先声明
- send(ac,p_buf,sizeof(p_buf),0);
-
- //char l_buf[32]={0};
- memset(l_buf,0,sizeof(l_buf));
- recv(ac,l_buf,sizeof(l_buf),0);//接收客户端发的信息:即客户端想要下载的文件名
- //printf("l_buf=%s\n",l_buf);
- //char h_buf[64]={0};
- memset(h_buf,0,sizeof(h_buf));
- sprintf(h_buf,"find ./ -name %s",l_buf);
- //用客户端发过来的文件名组成一个find命令的字符串,保存到h_buf
-
- //printf("h_buf =%s\n",h_buf);
- fy=popen(h_buf,"r");//执行find ./ -name xxxx
- memset(l_buf,0,sizeof(l_buf));
-
- fread(l_buf,1,sizeof(l_buf),fy);//将find命令执行后的信息,读取到l_buf
- //printf("l_buf=%s\n",l_buf);
- pclose(fy);
-
- /*在前面声明了一个结构体,这里需要注意,客户端那边定义的结构体和要和这个一样
- typedef struct file
- {
- char name[128];
- char cont[4096];
- }F;
- F f1; //定义结构体变量f1
- */
- if(strlen(l_buf)!=0)
- {
- //printf("find success\n");
- memset(f1.name,0,sizeof(f1.name));
-
-
- //这里用strncpy把后面的换行符删掉
- strncpy(f1.name,l_buf,strlen(l_buf)-1);
- printf("f1.name=%s\n",f1.name);
-
- //FILE*fu;
- fu = fopen(f1.name,"r+");
- if(fu==NULL)
- {
- perror("fopen failed");
- exit -1;
- }
-
- fseek(fu,0,SEEK_SET);
- memset(f1.cont,0,sizeof(f1.cont));
- fread(f1.cont,1,sizeof(f1.cont),fu);
- fclose(fu);
-
- printf("cont=%s\n",f1.cont);
- memcpy(r_buf,&f1,sizeof(f1));//这里先搞清楚memcpy函数
-
- send(ac,r_buf,sizeof(r_buf),0);
-
-
- }
- else
- {
- //char b_buf[64]="Filename is inexistent, Enter'download' try again";
- send(ac,b_buf,sizeof(b_buf),0);
-
- }
-
- }
- //下面代码加在客户端的父程序中,在前面声明char client_buf[5120]={0};
-
- if(strlen(client_buf)!=0)
- {
-
- /* typedef struct file
- {
- char name[128];
- char cont[4096];
- }D;
- D d1;
- */
-
- memset(&d1,0,sizeof(d1));
- memcpy(&d1,client_buf,sizeof(d1));
- //使用strstr函数,请先搞清楚strstr函数
- p = strstr(d1.name,"./");//将文件名保存到p中,在前面声明char*p;
- if(p) //如果d1的第一个元素中找到"./"字符
- {
- printf("p = %s\n",p);
- //FILE* fl;
- fl=fopen(p,"w+");//创建文件
-
- fwrite(d1.cont,1,strlen(d1.cont),fl);
- //将接收到的文件内容写入刚才创建的文件
- fseek(fl,0,SEEK_SET);
- fclose(fl);
- }
-
- else
- {
- // printf("not found\n");
- printf("receive data from server:%s\n",client_buf);
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。