您好,欢迎访问三七文档
软件学院信息安全产品开发实践实验七报告陈枝-10431110342012-11-02四川大学计算机学院、软件学院实验报告学号:_1043111034_姓名:_陈枝_专业:_软件工程_班级:_3班_第九周课程名称信息安全产品开发实践实验课时2实验项目并发服务器(一)实验时间第九周2012年11月02日星期五2012年11月02日星期五实验目的•服务器模型•多进程服务器模型实验环境X86,WindowsXP,VMware5.0,RedHatLinux9.0实验内容(算法、程序、步骤和方法)试验题目1•自己编写程序实现远程控制系统中使用到函数popen功能;思路:使用管道pipe(intf_des[2])函数(参数f_des[0]用于读取管道,f_des[1]用于向管道写入数据),通过管道实现父子进程间通讯;步骤:1.创建管道;2.创建子进程;3.在父进程中:关闭f_des[1],使用wait操作与等待子进程,然后将管道中的数据读出打印显示;4.在子进程:关闭f_des[0],将管道f_des[1]与标准输出进行重定向(dup2(f_des[1],STDOUT_FILENO)),然后调用execvp()函数执行程序中接收到的命令;试验题目2•修改远程控制服务器代码,使得服务器同时能够向多个用户提供服务数据记录和计算程序源码:题目1:FILE*mypopen(char*cmd,chartype){intpipefd[2];//管道描述符intpid_t;//进程描述符if(type!='r'&&type!='w'){printf(myopen()flagerror/n);returnNULL;}if(pipe(pipefd)0)//建立管道{printf(myopen()pipecreateerror/n);returnNULL;}pid_t=fork();//建立子进程if(pid_t0)returnNULL;if(0==pid_t)//子进程中......{if(type=='r'){close(pipefd[0]);//此函数返回文件指针是用于读,因此,在子进程中应该将结果写入管道,//这样父进程返回的文件指针才能读,所以这里将读端关闭dup2(pipefd[1],STDOUT_FILENO);//exec函数的执行结果将会通过标准输出写到控制台上,//但这里我们不需要在控制台输出,而是需要将结果返回,因此将标准输出重定向到管道写端close(pipefd[1]);}else{close(pipefd[1]);dup2(pipefd[0],STDIN_FILENO);close(pipefd[0]);}char*argv[]={cmd,NULL};if(execvp(cmd,argv)0)//用exec族函数执行命令returnNULL;}wait(0);//等待子进程返回if(type=='r'){close(pipefd[1]);returnfdopen(pipefd[0],r);//由于程序需要返回的参数是文件指针,因此需要用fdopen函数将描述符打开,其返回值为相应的文件指针}else{close(pipefd[0]);returnfdopen(pipefd[1],w);}}题目2:#includestdio.h#includestdlib.h#includestring.h#includesys/socket.h#includenetinet/in.h#includesys/types.h#includeunistd.h#definePORT8900#defineBUFSIZE2048voidprocesschild(intclientsoket);FILE*mypopen(char*cmd,chartype){intpipefd[2];//管道描述符intpid_t;//进程描述符if(type!='r'&&type!='w'){printf(myopen()flagerror/n);returnNULL;}if(pipe(pipefd)0)//建立管道{printf(myopen()pipecreateerror/n);returnNULL;}pid_t=fork();//建立子进程if(pid_t0)returnNULL;if(0==pid_t)//子进程中......{if(type=='r'){close(pipefd[0]);//此函数返回文件指针是用于读,因此,在子进程中应该将结果写入管道,//这样父进程返回的文件指针才能读,所以这里将读端关闭dup2(pipefd[1],STDOUT_FILENO);//exec函数的执行结果将会通过标准输出写到控制台上,//但这里我们不需要在控制台输出,而是需要将结果返回,因此将标准输出重定向到管道写端close(pipefd[1]);}else{close(pipefd[1]);dup2(pipefd[0],STDIN_FILENO);close(pipefd[0]);}char*argv[]={cmd,NULL};if(execvp(cmd,argv)0)//用exec族函数执行命令returnNULL;}wait(0);//等待子进程返回if(type=='r'){close(pipefd[1]);returnfdopen(pipefd[0],r);//由于程序需要返回的参数是文件指针,因此需要用fdopen函数将描述符打开,其返回值为相应的文件指针}else{close(pipefd[0]);returnfdopen(pipefd[1],w);}}intexecute(char*command,char*buf){FILE*fp;intcount;charcommandbuf[2056];if((NULL==command)||(NULL==buf)){perror(commandorbufisempty\n);return-1;}count=0;memset(commandbuf,0,2056);strcat(commandbuf,sh-c);strcat(commandbuf,command);fprintf(stderr,thecommandis%s\n,commandbuf);charar='r';if(NULL==(fp=mypopen(commandbuf,ar))){perror(createpipeerror\n);return-1;}while((count2047)&&(EOF!=(buf[count++]=fgetc(fp))));buf[count-1]='\0';returncount;}intmain(){intsockfd;structsockaddr_inclient;structsockaddr_inserver;intopt;intcnt;intaddr_len=sizeof(client);/*Thefirststage:INITILIZE*/memset(&client,0,sizeof(client));memset(&server,0,sizeof(server));sockfd=-1;opt=SO_REUSEADDR;/*Thesecondstage:createlistensocket*/if(-1==(sockfd=socket(AF_INET,SOCK_STREAM,0))){perror(createsocketerror\n);return-1;}setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));/*Thethirdstage:bindsocket*/server.sin_family=AF_INET;server.sin_addr.s_addr=htonl(INADDR_ANY);server.sin_port=htons(PORT);if(-1==bind(sockfd,(structsockaddr*)&server,sizeof(server))){perror(bindsocketerror\n);close(sockfd);return-1;}if(listen(sockfd,5)0){perror(listensocketerror\n);exit(1);}/*Thefifthstage:creatconnectsocket*/while(1){intclientsocket;clientsocket=accept(sockfd,(structsockaddr*)&client,(socklen_t*)&addr_len);if(clientsocket0){perror(error:acceptclientsocket!!\n);continue;}intpid=fork();if(pid0){close(clientsocket);continue;}elseif(pid==0){close(sockfd);processchild(clientsocket);exit(0);}else{printf(error:forkchildprocess!!);}}close(sockfd);}voidprocesschild(intclientsocket){charbuffer[BUFSIZE];intiDatanum;intcnt;charsendbuf[BUFSIZE];intsendnum;while(1){iDatanum=recv(clientsocket,buffer,BUFSIZE,0);if(0iDatanum){perror(error:Recvdata!!);exit(0);}buffer[iDatanum]='\0';fprintf(stderr,thecommandis:%s\n,buffer);if(0==strcmp(buffer,quit)){fprintf(stderr,theclientisquit\n);close(clientsocket);exit(0);}if(1=(cnt=execute(buffer,sendbuf))){sprintf(sendbuf,theinvalidcommand,pleasetryagain\n);}fprintf(stderr,theresultis\n%s,sendbuf);if(0=(sendnum=write(clientsocket,sendbuf,strlen(sendbuf)))){perror(thecommucationerror\n);close(clientsocket);exit(0);}}close(clientsocket);}结论(结果)结果截图:小结通过本实验,我掌握了:服务器模型种类以及多进程服务器模型;并发服务模型在linux中提供了三种方式支持并发模型:多进程,多线程,I/O多路复用;自己编写程序实现远程控制系统中使用到函数popen功能;自己还学会修改远程控制服务器代码,使得服务器同时能够向多个用户提供服务。指导老师评议成绩评定:指导教师签名:
本文标题:并发服务器(1)
链接地址:https://www.777doc.com/doc-3606882 .html