信息安全产品开发实践 并发服务器II――多线程

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

四川大学计算机学院、软件学院实验报告学号:_1143111172_姓名:_柴承训_专业:_软件工程_班级:_9班_第7周课程名称信息安全产品开发实践实验课时5实验项目并发服务器II——多线程实验时间2013.10.25实验目的1)继续了解Linux下C语言程序开发的过程2)了解线程库Pthreads及提供的基本线程的操作线程的属性,了解线程的属性,线程的互斥和同步3)掌握多线程网络服务器模型4)能在Linux环境实现TCP多线程并发服务器模型5)能编写多线程端口扫描程序实验环境X86,WindowsXP,VMwareWorkstation5.0.0,RedHatLinux,SSHSecureShellClient-3.2.9实验内容(算法、程序、步骤和方法)试验题目1修改远程控制程序服务器程序,将其从循环模式或多进程模式修改为多线程模式试验题目2多线程端口扫描程序实现一个多线程端口扫描程序:要求:1.能同时扫描5个IP地址;2.针对每个iP地址,开设100个线程对其进行扫描;3.如果端口打开,使用函数getservbyport获取其服务名,在屏幕上打印:IPportservername,如果是未知服务,则屏幕显示:ipportunkonown实验一:先来回顾一下上次实验实现的多进程并发服务器:Unix下的大多数网络服务器程序都是这么编写的,即父进程接受连接,派生子进程,子进程处理与客户的交互。虽然这种模型很多年来使用得很好,但是fork时有一些问题:(1)fork是昂贵的。内存映像要从父进程拷贝到子进程,所有描述字要在子进程中复制等等。目前有的Unix实现使用一种叫做写时拷贝(copy-on-write)的技术,可避免父进程数据空间向子进程的拷贝。尽管有这种优化技术,fork仍然是昂贵的;(2)fork子进程后,需要用进程间通信(IPC)在父子进程之间传递信息。Fork之前的信息容易传递,因为子进程从一开始就有父进程数据空间及所有描述字的拷贝。但是从子进程返回信息给父进程需要做更多的工作。;而上述两个问题可以通过用线程代替进程的方法来克服,接下来我们再来看下进程的一些特点:•线程有助于解决这两个问题。线程有时被称为轻权进程(lightweightprocess),因为线程比进程“轻权”,一般来说,创建一个线程要比创建一个进程快10~100倍。•一个进程中的所有线程共享相同的全局内存,这使得线程很容易共享信息,但是这种简易性也带来了同步问题。•一个进程中的所有线程不仅共享全局变量,而且共享:进程指令、大多数数据、打开的文件(如描述字)、信号处理程序和信号处置、当前工作目录、用户ID和组ID。•但是每个线程有自己的线程ID、寄存器集合(包括程序计数器和栈指针)、栈(用于存放局部变量和返回地址)、error、信号掩码、优先级。•程序的编译gcc–otesttest.c-lpthread有了这些理论准备之后我们就可以编程来实现我们的多线程并发服务器了。源代码:/**=====================================================================================**Filename:udpserver.c**Description:Thisprogramisusedtodemostratehowtoimplementaudprpcserver**Version:1.0*Created:2013骞?9鏈?4鏃?20鏃?9鍒?2绉?*Revision:none*Compiler:gcc**Author:GangLiang*Organization:ComputerScienceCollege,SichuanUniverstiy**=====================================================================================*/#includestdio.h#includestdlib.h#includestring.h#includesys/socket.h#includenetinet/in.h#includesys/types.h#includeunistd.h#includepthread.h#includearpa/inet.h#definePORT8888/*serverport*/#defineSIZE2048/*2KBUFFER*/void*start_routine(void*arg);//声明线程处理函数intexec(char*command,char*result){FILE*in;intlen;charc;len=0;bzero(result,sizeof(result));in=popen(command,r);if(NULL==in){fprintf(stderr,errorincreateapipe\n);return-1;}while(((c=fgetc(in))!=EOF)&&(lenSIZE)){result[len]=c;len++;}result[len]='\0';pclose(in);if(0==len){sprintf(result,%scannotexecute\n,command);}returnlen;}/*-----endoffunctionexec-----*//**===FUNCTION======================================================================*Name:main*Description:*=====================================================================================*/intmain(intargc,char*argv[]){intthread;intsockfd;/*socket*/structsockaddr_inclient;/*ipaddressofclient*/structsockaddr_inserver;/*ipaddressofserver*/intlen;intport;intrvalue;charsend_buf[SIZE];/*theresultofbuffer*/charrecv_buf[SIZE];/*thecommandbuffer*/charcmd[10];/*thesetwovarusedtodealwithcdcommand*/charpath[2048];intopt;intconnected;//initsockfd=-1;bzero(&client,sizeof(structsockaddr));bzero(&server,sizeof(structsockaddr));len=-1;rvalue=-1;bzero(send_buf,SIZE);bzero(recv_buf,SIZE);port=PORT;bzero(cmd,10);bzero(path,2048);opt=SO_REUSEADDR;connected=-1;//phrase1:createsocket;sockfd=socket(AF_INET,SOCK_STREAM,0);/*generatethesocket*/if(-1==sockfd){fprintf(stderr,errorincreatingsocket\n);exit(-1);}setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));//phrase2:bindthesocketserver.sin_family=AF_INET;server.sin_port=htons(port);server.sin_addr.s_addr=htonl(INADDR_ANY);rvalue=bind(sockfd,(structsockaddr*)&server,sizeof(structsockaddr));if(-1==rvalue){fprintf(stderr,errorinbindingsocket\n);close(sockfd);exit(-1);}//listensocketif(-1==listen(sockfd,10)){perror(listensocketerror\n);close(sockfd);return-1;}//phrase3:communicationwithclient.Attention:Theclientsendmessagetoserverfirst,thentheserver//cansendmessagetotheclient.Otherwise,servercannotkonwabouttheclientwhile(1){len=sizeof(structsockaddr);if(-1==(connected=accept(sockfd,(structsockaddr*)&client,&len))){perror(threeshakehandserror\n);close(sockfd);return-1;}//调用线程函数if(pthread_create(&thread,NULL,(void*)start_routine,(void*)connected)){perror(Pthread_create()error);exit(1);}close(connected);}//phrase4:releasethesocketclose(sockfd);returnEXIT_SUCCESS;}//线程函数的实现void*start_routine(void*arg){intconn_sock=arg;intsockfd;charsendbuf[SIZE];charrecvbuf[SIZE];intsendnum;intrecvnum;intlength;intopt;intcnt;while(1){close(sockfd);memset(recvbuf,0,SIZE);memset(sendbuf,0,SIZE);if(0=(recvnum=read(conn_sock,recvbuf,SIZE))){perror(thecommucationerror\n);close(conn_sock);close(sockfd);return-1;}recvbuf[recvnum]='\0';fprintf(stderr,thecommandis:%s\n,recvbuf);if(0==strcmp(recvbuf,quit)){fprintf(stderr,theclientisquit\n);close(conn_sock);break;}if(1=(cnt=exec(recvbuf,sendbuf))){sprintf(sendbuf,theinvalidcommand,pleasetryagain\n);}fprintf(stderr,theresultis\n%s,sendbuf);if(0=(sendnum=write(conn_sock,sendbuf,strlen(sendbuf)))){perror(thecommucationerror\n);close(conn_sock);return-1;}}close(sockfd);}/*----------endoffunctionmain----------*/实验截图:实验二:实验思路;主要分为以下四个部分:(1):从控制端接受用户的输入;(2):根据用户的输入结果,根据IP地址创建100线程进行扫描1.创建100个线程描述符pidthread_t*thread

1 / 15
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功