并发服务器(一)_第1页
并发服务器(一)_第2页
并发服务器(一)_第3页
并发服务器(一)_第4页
并发服务器(一)_第5页
已阅读5页,还剩27页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、四 川 大 学 计 算 机 学 院、软 件 学 院实 验 报 告 课程名称 信息安全产品开发实践 实验课时5实验项目并发服务器(一) 实验时间2011年10月09号实验目的 1) 继续了解Linux下C语言程序开发的过程2) 掌握服务器分为哪几种模型3) 能在Linux环境实现TCP多进程并发服务器模型4) 了解什么是僵尸程序 及相应的解决方法实验环境 VMware5.0,RedHat Linux 9.0实验内容(算法、程序、步骤和方法) 试验题目1 自己编写程序实现远程控制系统中使用到函数popen功能;试验题目2 修改远程控制服务器代码,使得服务器同时能够向多个用户提供服务。在开始这次实验

2、之前,我们先来了解一下现在常见的服务器模型:现在的服务器一般分为两种模型:(1)循环(重复)服务器模型:每次只能处理一个客户的请求,但上一个客户的请求完成后,才能处理下一个客户的请求;(2)并发服务器模型:服务器在同一时刻可以响应多个客户的请求;接着我们需要了解如何去实现这两类服务器模型,通常来说实现服务器程序不外乎利用UDP和TCP两种方式。下面来看下具体的流程:UDP:(1):UDP重复模型 UDP循环服务器的实现非常简单:UDP服务器每次从套接字上读取一个客户端的请求,处理,然后将结果返回给客户机. socket(.); bind(.); while(1) recvfrom(.); pr

3、ocess(.); sendto(.); (2):UDP并发服务器 人们把并发的概念用于UDP就得到了并发UDP服务器模型.并发UDP服务器模型其实是简单的.和并发的TCP服务器模型一样是创建一个子进程来处理的算法和并发的TCP模型一样. 除非服务器在处理客户端的请求所用的时间比较长以外,人们实际上很少用这种模型.TCP:(1):TCP重复服务器模型 socket(.); bind(.); listen(.); while(1) accept(.); while(1) read(.); process(.); write(.); close(.); TCP服务器接受一个客户端的连接,然后处理,

4、完成了这个客户的所有请求后,断开连接. (2):TCP多进程并发服务器模型socket(.); bind(.); listen(.); while(1) accept(.); if(fork(.)=0) Close(listenfd) while(1) read(.); process(.); write(.); close(.); exit(.); close(.); else if (fork()0) close(accept); continue; 接下来我们在来看一下 在Linux下支持并发服务器模型的方式。一般来说有下面的三种方式:(1) 多进程(2) 多线程(3) I/O多路复用在

5、经过上面这么多得理论的分析之后,我们对服务器的类别及实现方法有了大致的了解。回顾第四周做得实验,我们知道之前做得用TCP和UDP实现服务器端和客户端的方式都属于循环服务器模型,即服务器在一个阶段之内只能处理一个客户,并且只有在一个客户被处理完之后才能继续相应下一个客户的请求。那门我们今天就要实现并发服务器模型。进一步分析,我们得之,如果是用UDP实现的循环服务器,那么它同时也是并发服务器,即不需要任何修改,之前的循环UDP服务器就能实现UDP并发服务器的功能,因为UDP在服务器与客户端通信是不需要建立连接的。所以我们今天的工作就是编程实现TCP并发服务器模型。由于基本原理之前类似,所以我们只需

6、要在原来的程序上做少量的修改,就可以实现TCP的并发服务器。下面进入实验。实验一:实验步骤:(1):popen() 函数的作用是用创建管道的方式启动一个进程。在第四周的试验中我们通过这个函数完成了远程控制系统的编写。今天我们就自己编写函数来代替popen()函数,达到同样的效果。(2) :先来分析一下思路:我们可以利用使用管道pipe(int f_des2)函数(参数f_des0用于读取管道,f_des1用于向管道写入数据),通过管道实现父子进程间通讯。(3) 所以程序可以分为以下四个部分:1.创建管道;2.创建子进程;3.在父进程中:关闭f_des1,使用wait操作与等待子进程,然后将管道

7、中的数据读出打印显示;4.在子进程:关闭f_des0,将管道f_des1与标准输出进行重定向(dup2(f_des1,STDOUT_FILENO)),然后调用execvp()函数执行程序中接收到的命令;(4)接下来我们就可以编写自己的程序了,打开虚拟机,利用VI编辑器将我们的程序命名为mypopen.c(5)保存mypopen.c,使用命令gcc o mypopen mypopen.c g命令编译程序。(6)执行./mypopen,输入命令:ls(7) 再次执行./mypopen,输入命令who(8) 执行命令./mypopen,输入命令:pwd(9) 经过以上步骤的验证,说明我们自己编写的m

8、ypopen.c函数正确的实现了popen()的功能。本函数与Linux中的popen()函数实现最大的不同是不需要用专门的pclose()函数来关闭文件指针,用普通的fclose()即可。实验二:实验步骤:(1):就像之前说得实现TCP并发服务器有三种方式,今天我们利用多进程的方式来实现这个目的。在编写TCP的并发服务器之前,我们先来看下TCP多进程并发模型的流程图。(2):根据流程图我们就可以在Linux进行程序的编写了,打开虚拟机,在Linux下的VI编辑器中编写服务器端程序tcpserver.c上述红色区域是代码修改的地方,而且在头文件需加入#include (3)使用命令gcc o

9、tcpserver tcpserver.c g编译; (4):编写客户端代码,客户端代码是不需要修改的,在vi下编辑tcpclient.c,保存,编译。(5)打开一个终端,执行服务器端程序./tcpserver(6) 打开第二个终端,执行第一个客户端命令./tcpclient 127.0.0.1(7)打开第三个终端,执行第二个客户端命令./tcpclient 127.0.0.1(8)第一个客户端程序继续输入命令:who(9): 第二个客户端程序继续输入命令:who(接上)实验内容(算法、程序、步骤和方法) (10):第一个客户端程序继续输入命令:quit(11):第二个客户端程序继续输入命令:

10、quit(12):从上面的演示效果来看程序很好的实现了并发服务器的功能,即服务器在同一阶段能与多个客户进行通信。附试验源代码:mypopen.c/mypopen.c#include #include #include #include int main(int argc,char *argv)pid_t pid;int f_des2;char cmd1024;printf(Please input your command:);scanf(%s,&cmd);if(-1=pipe(f_des)perror(create pipe errorn);exit(1);if(pid=fork()0)pr

11、intf(This is in parent processn);close(f_des1);wait();char buffer1024;int readByte = read(f_des0,buffer,sizeof(buffer);bufferreadByte = 0;printf(The message is :%s n,buffer);exit(0);else close(f_des0);dup2(f_des1,STDOUT_FILENO);char *argv=cmd,NULL;execvp(cmd,argv);exit(0);tcpserver.c/tcpserver.c#inc

12、lude #include #include #include #include #include #include #define PORT 8900#define BUFSIZE 2048int execute(char*command,char*buf)FILE *fp;int count;char commandbuf2056;if (NULL=command)|(NULL=buf)perror(command or buf is emptyn);return -1;count =0;memset(commandbuf,0,2056);strcat(commandbuf,sh -c )

13、;strcat(commandbuf,command);fprintf(stderr,the command is %sn,commandbuf);if (NULL=(fp=popen(commandbuf,r)perror(create pipe errorn);return -1;while (count2047) & (EOF!=(bufcount+=fgetc(fp);bufcount-1=0;return count;int main()int sockfd;/pid_t pid;int conn_sock;char sendbufBUFSIZE;char recvbufBUFSIZ

14、E;int sendnum;int recvnum;int length;struct sockaddr_in client;struct sockaddr_in server;int opt;int cnt; /* The first stage:INITILIZE */memset(&client,0,sizeof(client);memset(&server,0,sizeof(server);memset(sendbuf,0,BUFSIZE);memset(recvbuf,0,BUFSIZE);length=0;sockfd=-1;conn_sock=-1;opt=SO_REUSEADD

15、R;/*The second stage:create listen socket */if (-1=(sockfd=socket(AF_INET,SOCK_STREAM,0)perror(create socket errorn);return -1;setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt);/* The third stage:bind socket */server.sin_family=AF_INET;server.sin_addr.s_addr=htonl(INADDR_ANY);server.sin_por

16、t=htons(PORT);if (-1=bind(sockfd,(struct sockaddr*)&server,sizeof(server)perror(bind socket errorn);close(sockfd);return -1;/* The fourth stage:listen socket */if (-1=listen(sockfd,10)perror(listen socket errorn);close(sockfd);return -1;/* The fifth stage:creat connect socket */while(1)if (-1=(conn_

17、sock=accept(sockfd,(struct sockaddr*)&client,&length)perror(three shakehands errorn);close(sockfd);return -1;pid_t pid;if (pid=fork() 0)printf(This is the parent process);continue;/* the commnication with client */else while(1)close(sockfd);memset(recvbuf,0,BUFSIZE);memset(sendbuf,0,BUFSIZE);if (0=(

18、recvnum=read(conn_sock,recvbuf,BUFSIZE)perror(the commucation errorn);close(conn_sock);close(sockfd);return -1;recvbufrecvnum=0;fprintf(stderr,the command is:%sn,recvbuf);if (0=strcmp(recvbuf,quit)fprintf(stderr,the client is quitn);/fprintf(stderr,list);close(conn_sock);exit(1);if (1=(cnt=execute(r

19、ecvbuf,sendbuf)sprintf(sendbuf,the invalid command,please try againn);fprintf(stderr,the result is n%s,sendbuf);if (0=(sendnum=write(conn_sock,sendbuf,strlen(sendbuf)perror(the commucation errorn);close(sockfd);close(conn_sock);return -1;close(sockfd);tcpclient.c/tcpclient.c#include #include #includ

20、e #include #include #include #define PORT 8900#define BUFSIZE 2048void printusage(char*command)if (NULL=command)exit(-1);fprintf(stderr,the useage of %s :,command);fprintf(stderr,%s IPADDRn,command);return;int main(int argc,char* argv)int sockfd;int length;struct sockaddr_in server;int sndnum;int re

21、cvnum;char sendbufBUFSIZE;char recvbufBUFSIZE;sockfd=-1;length=0;if (2!=argc)printusage(argv0);return -1;if (-1=(sockfd=socket(AF_INET,SOCK_STREAM,0)perror(create socket errorn);return -1;memset(&server,0,sizeof(server);server.sin_family=AF_INET;server.sin_addr.s_addr = inet_addr(argv1);server.sin_p

22、ort = htons(PORT);if (-1=connect(sockfd,(struct sockaddr*)&server,sizeof(server)perror(connect errorn);close(sockfd);return -1;while(1)fprintf(stderr,TCP);memset(recvbuf,0,BUFSIZE);memset(sendbuf,0,BUFSIZE);fgets(sendbuf,BUFSIZE,stdin);length=strlen(sendbuf);sendbuflength-1=0;if (0=(sndnum=write(soc

23、kfd,sendbuf,strlen(sendbuf)perror(send errorn);close(sockfd);exit(-1);if (0=strcmp(sendbuf,quit)fprintf(stderr,quit.n);close(sockfd);exit(0);if (0=(recvnum=read(sockfd,recvbuf,BUFSIZE)perror(read errorn);close(sockfd);exit(-1);recvbufrecvnum=0;fprintf(stderr,the result:n);fprintf(stderr,%sn,recvbuf);数据记录和计算 详细见上面结 论(结 果) (1)利用管道技术可以自己编写函数实

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论