信息安全产品开发实践并发服务器II多线程.docx
- 文档编号:11904135
- 上传时间:2023-06-03
- 格式:DOCX
- 页数:16
- 大小:122.45KB
信息安全产品开发实践并发服务器II多线程.docx
《信息安全产品开发实践并发服务器II多线程.docx》由会员分享,可在线阅读,更多相关《信息安全产品开发实践并发服务器II多线程.docx(16页珍藏版)》请在冰点文库上搜索。
信息安全产品开发实践并发服务器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
有了这些理论准备之后我们就可以编程来实现我们的多线程并发服务器了。
源代码:
/*
*=====================================================================================
*
*:
udpserver.c
*
*Description:
Thisprogramisusedtodemostratehowtoimplementaudprpcserver
*
*Version:
1.0
*Created:
2013骞?
9鏈?
4鏃?
20鏃?
9鍒?
2绉?
*Revision:
none
*Compiler:
gcc
*
*Author:
GangLiang
*Organization:
ComputerScienceCollege,SichuanUniverstiy
*
*=====================================================================================
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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)&&(len { 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; //init sockfd=-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: bindthesocket server.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); } //listensocket if(-1==listen(sockfd,10)) { perror("listensocketerror\n"); close(sockfd); return-1; } //phrase3: communicationwithclient.Attention: Theclientsendmessagetoserverfirst,thentheserver //cansendmessagetotheclient.Otherwise,servercannotkonwabouttheclient while (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: releasethesocket close(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; thread=(pthread_t*)malloc(THREAD_NUM*sizeof(pthread_t)); 2.为每个线程创建扫描的分工 for(intj=0;j for(inti=0;i port_segmentport; port.dest=dest_ip[j]; port.min_port=i*SEG_LEN+1; /*thelastsegment*/ if(i==(THREAD_NUM-1)) port.max_port=MAX_PORT; else port.max_port=port.min_port+SEG_LEN-1; (3): 创建线程,开始扫描 if(pthread_create(&thread[i],NULL,scan,(void*)&port)! =0) { perror("pthread_createfailed\n"); free(thread); exit(-2); } (4): 释放创建的资源 free(pthread); 源代码: #include #include #include #include #include #include #include #include #include #defineNUM100 #defineMAX_PORT65535 #defineSEG_LEN655 typedefstructport_segment { int*ip; unsignedmin_port; unsignedmax_port; }port_segment; void*scan(void*arg); intmain(intargc,char**argv) { intj,i; pthread_t*thread; thread=(pthread_t*)malloc(NUM*sizeof(pthread_t)); if((argc<2)||(argc>6)) { printf("inputerror! \n"); } for(j=1;j { for(i=0;i { port_segment*port=(port_segment*)malloc(sizeof(port_segment)); port->ip=argv[j]; port->min_port=i*SEG_LEN+1; if(i==(NUM-1)) port->max_port=MAX_PORT; else port->max_port=port->min_port+SEG_LEN-1; if(pthread_create(&thread[i],NULL,scan,(void*)port)! =0) { perror("pthread_creatfail! "); free(thread); exit(-2); } } } return0; } void*scan(void*arg) { structsockaddr_inserver; inti,sockfd,con; pthread_detach(pthread_self()); port_segment*port=(port_segment*)arg; memset(&server,0,sizeof(structsockaddr_in)); server.sin_family=AF_INET; server.sin_addr.s_addr=inet_addr(port->ip); for(i=port->min_port;i<=port->max_port;i++) { server.sin_port=htons(i); if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) { perror("cannotcreatesocket\n"); exit (1); } if((con=connect(sockfd,(structsockaddr*)&server,sizeof(structsockaddr)))==0) { structservent*sp; sp=getservbyport(htons(i),"tcp"); if(sp! =NULL) printf("%d\t%s\n",i,sp->s_name); else printf("%d\tunkown! \n",i); } close(sockfd); } } 截图: 结论 (结果) •运行正确,能同时支持多客户端 小结 通过本实验,我掌握了: 1)进一步熟悉了Linux下C语言程序开发的过程; 2)了解了一些基本的线程函数 3)掌握了如何利用多线程实现并发服务器 4)会编写多线程端口扫描程序 指导老师评议 成绩评定: 指导教师签名:
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 信息 安全产品 开发 实践 并发 服务器 II 多线程