您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 管理学资料 > 网络软件设计5——并发与重复服务
网络软件设计并发服务与重复服务ConcurrentServiceRepeatingService制作主讲段景山段景山引入基本流程下的服务器程序在多个客户同时连接服务器时,只能为一个客户提供服务。2段景山31、基本思想1.1重复服务仅使用一个服务器进程依次为每个用户服务s=socket(SOCK_STREAM);bind(s,…);listen(s,5);while(1){ns=accept(s,…);recv(ns,…);send(ns,…);closesocket(ns);}closesocket(s);监听套接字连接服务套接字连接服务套接字连接服务套接字循环—重复段景山4基本思想1.2并发服务利用多个进程“同时”为各用户请求服务主进程子进程1子进程2监听套接字创建连接服务套接字连接服务套接字相关知识进程线程并发并行多任务系统调度*单CPU系统监听到连接段景山52、重复服务方式实现2、重复服务方式的实现s=socket(SOCK_STREAM);bind(s,…);listen(s,5);while(1){ns=accept(s,…);recv(ns,…);send(ns,…);closesocket(ns);}closesocket(s);段景山6并发服务实现3并发服务方式的实现3.1并发服务程序流程——流程驱动s=socket(SOCK_STREAM);bind(s,…);listen(s,5);while(1){ns=accept(s,…);}closesocket(s);主进程创建子进程,并将ns传递给子进程子进程(ns)while(recv(ns,…)0){printf(buf);send(ns,”ACK”,…);}……closesocket(ns);关键技术完成通信父进程为每一条连接生成一个子进程每个子进程在相应的连接上完成通信段景山7并发服务实现3.2UNIX并发服务的实现3.2.1、fork()main(){inti;sum=0;fork();for(i=1;i=10000;i++){printf(”thevalueofiis%d“,i);fflush(stdout);sum+=i;}printf(“thetotalis%d”,sum);exit(0);}fork():创建一个新进程,新进程是父进程的复制品--数据、代码因此新进程将完成和父进程同样的功能.段景山8main(){inti;sum=0;fork();for(i=1;i=10000;i++){printf(”thevalueofiis%d“,i);fflush(stdout);sum+=i;}printf(“thetotalis%d”,sum);exit(0);}并发服务实现main(){inti;sum=0;fork();for(i=1;i=10000;i++){printf(”thevalueofiis%d“,i);fflush(stdout);sum+=i;}printf(“thetotalis%d”,sum);exit(0);}主进程子进程子进程从这里开始段景山9并发服务的实现执行结果main(){inti;sum=0;fork();for(i=1;i=10000;i++){printf(”thevalueofiis%d\n“,i);fflush(stdout);sum+=i;}printf(“thetotalis%d”,sum);exit(0);}thevalueofiis1thevalueofIis2thevalueofiis3thevalueofiis4thevalueofiis1thevalueofIis2thevalueofiis3thevalueofiis4thevalueofiis5thevalueofIis6thevalueofiis7thevalueofiis5thevalueofiis6thevalueofIis7thevalueofiis8thevalueofiis8主/子进程并发执行(分时调度)进程x进程y进程x进程y思考:sum的结果段景山10并发服务的实现3.2.2fork()与并发通信服务main(){inti;sum=0;fork();for(i=1;i=10000;i++){printf(”thevalueofiis%d\n“,i);fflush(stdout);sum+=i;}printf(“thetotalis%d”,sum);exit(0);}Back初始化主要工作Servers=socket(SOCK_STREAM);bind(s,…);listen(s,5);while(1){ns=accept(s,…);recv(ns,…);send(ns,…);closesocket(ns);}closesocket(s);建立连接通信fork();段景山11并发服务的实现Servers=socket(SOCK_STREAM);bind(s,…);listen(s,5);while(1){ns=accept(s,…);recv(ns,…);send(ns,…);closesocket(ns);}closesocket(s);fork();Servers=socket(SOCK_STREAM);bind(s,…);listen(s,5);while(1){ns=accept(s,…);recv(ns,…);send(ns,…);closesocket(ns);}closesocket(s);fork();问题:如何使主/子进程完成不同的工作?主进程:不断建立连接,创建子进程子进程:完成连接上的通信段景山12并发服务的实现3.2.3进程的分离新进程执行与父进程不同的代码利用fork()的返回值。fork()后父进程得到的返回值为子进程标识符(非零)fork()后子进程得到的返回值为0为新进程更换代码——execve()fork();execve();段景山13并发服务的实现法一、利用fork返回值分离进程s=socket(SOCK_STREAM);bind(s,…);listen(s,5);while(1){ns=accept(s,…);recv(ns,…);send(ns,…);closesocket(ns);}closesocket(s);fork();pid=fork();if(pid==0){closesocket(s)recv(ns,…);send(ns,…);……exit(0);}else{closesocket(ns);}思考:主进程与子进程是如何分离的?为什么在子进程中要关闭s为什么在主进程中要关闭ns子进程如何结束,父进程如何结束子进程父进程段景山14s=socket(SOCK_STREAM);bind(s,…);listen(s,5);while(1){ns=accept(s,…);pid=fork();if(pid==0){closesocket(s)recv(ns,…);send(ns,…);……exit(0);}else{closesocket(ns);}SOCKETs,ns;intpid;并发服务的实现s=socket(SOCK_STREAM);bind(s,…);listen(s,5);while(1){ns=accept(s,…);pid=fork();if(pid==0){closesocket(s)recv(ns,…);send(ns,…);……exit(0);}else{closesocket(ns);}主进程子进程SOCKETs,ns;intpid;系统往pid中放入子进程id系统往pid中放入0段景山15并发服务的实现法二、用execve()替换子进程代码可以使子进程具有与父进程不同的代码intexecve(constchar*pathname,constchar*argv[],constchar*envp[])pathname:子进程执行的程序路径名argv:传递给子进程的参数表envp:指定子进程的新环境段景山16并发服务的实现s=socket(SOCK_STREAM);bind(s,…);listen(s,5);while(1){ns=accept(s,…);pid=fork();if(pid==0){closesocket(s);argv[1]=ns;execve(“user/bin/chat”,argv,NULL);}else{closesocket(ns);}}Chat.cmain(argc,argv){SOCKETs;s=argv[1];recv(s,…);send(s,…);closesocket(s);}段景山17并发服务的实现3.3Windows并发服务的实现CreateThread--生成线程CreatePorcess--生成进程线程执行指定的代码段线程之间并发执行与UNIX下的fork()+execve方法类似相关知识:线程与进程的区别和联系段景山18并发服务的实现3.3.1CreateThreadHANDLECreateThread(LPSECURITY_ATTRIBUTESlpThreadAttributes,DWORDdwStackSize,LPTHREAD_START_ROUTINElpStartAddress,LPVOIDlpParameter,DWORDdwCreationFlags,LPDWORDlpThreadId);lpStartAddress:线程代码入口点--线程函数指针lpParameter:传递给线程的参数lpThreadId:线程标识符--返回值函数返回值:线程句柄段景山19并发服务的实现DWORDWINAPIThreadFunc(LPVOIDlpParam){charszMsg[80];wsprintf(szMsg,ThreadFunc:Parameter=%d\n,*lpParam);MessageBox(NULL,szMsg,Threadcreated.,MB_OK);return0;}VOIDmain(VOID){DWORDdwThreadId,dwThrdParam=1;HANDLEhThread;hThread=CreateThread(NULL,0,ThreadFunc,&dwThrdParam,0,&dwThreadId);//returnsthethreadidentifier//Checkthereturnvalueforsuccess.if(hThread==NULL)ErrorExit(CreateThreadfailed.);CloseHandle(hThread);}生成线程的例程段景山20并发服务的实现3.3.2主线程代码s=socket(SOCK_STREAM);bind(s,…);listen(s,5);while(1){ns=accept(s,…);pid=fork();if(pid==0){closesocket(s);argv[1]=ns;execve(“user/bin/chat”,NULL,NULL);}else{closesocket(ns);}CreateThread(NULL,0,chat,//子线程函数入口¶m,//传给子线程的参数0,&Tid);param=malloc(sizeof(SOCKET));*param=ns;}段景山21并发服务的实现3.3.3子线程代码DWORDWINAPIchat(LPVOIDparam){SOCKETs;s=*(SOCKET*)param;recv(s,……);send(s,……)while(1){}closesocket(s);}free(param)段景山22小结并发服务机制具有多路复用功能服务器程序同时为多个客户提供服务并发执行的进程/线程同时为多条连接服务并发服务与上下文切换在并发执行的进程间调度,需要
本文标题:网络软件设计5——并发与重复服务
链接地址:https://www.777doc.com/doc-6339474 .html