共享参数的多线程编程_第1页
共享参数的多线程编程_第2页
共享参数的多线程编程_第3页
共享参数的多线程编程_第4页
共享参数的多线程编程_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

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

文档简介

哈尔滨理工大学课程设计题目:共享参数的多线程编程(网络安全课程设计)院、系:计算机科学与技术学院网络工程系班级:学号:姓名:同组成员:指导教师:成绩:2014年06月27日一系统设计的目标了解并掌握C/S模式下TCP的连接以及并发服务器的实现。了解并掌握多线程在实现共享参数方面的方法。3,掌握共享参数多线程编程。二系统原理实验环境:Ubuntu12.04系统,GCC编译器1),建立套接字并在某一约定端口上等待接收客户请求;2),当接收到来自客户端的服务请求后:建立一新线程来处理,同时主线程继续等待其他客户连接。当新线程处理完成后,关闭新线程与客户的通信链路并终止新线程。.关闭服务器。图2-1工作过程三系统功能分析.C/S结构介绍C/S结构,即大家熟知的客户机和服务器结构。它是软件系统体系结构,通过它可以充分利用两端硬件环境的优势,将任务合理分配到Client端和Server端来实现,降低了系统的通讯开销。(Client/Server或客户/服务器模式):Client和Server常常分别处在相距很远的两台计算机上,Client程序的任务是将用户的要求提交给Server程序,再将Server程序返回的结果以特定的形式显示给用户;Server程序的任务是接收客户程序提出的服务请求,进行相应的处理,再将结果返回给客户程序。C/S模式下TCP方式服务器程序流程(多进程):程序初始化填写本机地址信息绑定并监听一个固定的端口收到Client的连接后建立一个socket连接产生一个新的线程与Client进行通信和信息处理子通信结束后中断与Client的连接客户端程序流程:程序初始化填写服务器地址信息连接服务器与服务器通信和信息处理通信结束后断开连接.套接字技术所谓socket通常也称作"套接字”,应用程序通常通过"套接字”向网络发出请求或者应答网络请求。以J2SDK-1.3为例,Socket和ServerSocket类库位于包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。不管是Socket还是ServerSocket它们的工作都是通过Socketlmpl类及其子类完成的。.多线程并发服务器的实现线程,有时被称为轻量级进程(LightweightProcess,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。在一个进程中的多个线程之间,可以并发执行,甚至允许在一个进程中所有线程都能并发执行;同样,不同进程中的线程也能并发执行,充分利用和发挥了处理机与外围设备并行工作的能力。基于多线程的Linux系统下并发服务器能够同时并有效地运行多个任务。采用这种并发系统结构,既增加了服务器程序的功能,又提高了其性能。只有一个处理器时,多个线程不能真正地并行执行。然而,经过固定的时间间隔或当一个线程处于等待状态时,就可从一个线程切换到另一线程,实现多个线程重叠执行。在有多个CPU的计算机上,如果底层系统支持,则多个线程可真正地被并行执行服务的并行性潜力得以开发。四系统实现下面我们通过一个具体的实例来说明多线程并发服务器的具体实现:服务器端:循环等候客户连接请求一旦有客户连接请求开启一个子线程接受并处理客户请求连接成功后向客户发送欢迎信息,接着接受来自客户的信息,然后将客户信息反转后再返回给客户端主线程继续等待其他客户请求服务器具有同时处理多个用户的能力;客户端:首先与服务器建立连接,接着接收用户输入的客户名字,将名字发给服务器;然后向服务器发送数据,进行交互,接受服务器的反馈信息并显示之后继续等待用户输入直至用户输入ctrl+c结束通信客户端接到输入ctrl+c后客户端关闭连接并退出。实验截图客户端在命令行中应输入欲连接服务器的地址或域名,如图所示。覆knight©knight-Aspire-47501~kntght@knight-Aspire-4750*/client127-0,0*1ServerMessage:Welcometomyserver*Inputyourrbane:cltent991Inputyournessage(nax:I960)图4-1客户端请求连接

用户给出客户端名称,服务器端显示,如图所示,服务器端通过用户名来显示信息的来源,并对信息进行处理返回客户端,客户端在屏幕输出,如图❸0@knight©knight-Aspire-475D:~gcc:致命错误:编译中断。没有输入文件-oclientclienttic127.0,0.1knight@knight-Aspire-4759:./client127.0,0.1Binderror*:Connectionrefusedknight@knight-Aspire-4759:gcc-oserverserver^cgcc:错误:server.c::没有那个文件或目录gcc:致命错误:没有输入文件编译中断。-Lpthread-Lpthreadknight@knight-Aspire-4759:*/serverbash:./server:没有那个文件或目录knight@knight-Aspire-4759:gcc-oserverserver^cgcc:错误:server.c::-Lpthread-Lpthreadknight@knight-Aspire-4759:gcc-oserverserver^cknight@knight-Aspire-4759:*/serverYougetaconnectfrom127*0*0.1ClientnameisclientOOl.messagerwoshiknlghtmessage:nihaomfe"

message:ntrensht

message:nizhidaoRecetvefromclient(client©01)Yougetamessagerwoshiknlghtmessage:nihaomfe"

message:ntrensht

message:nizhidaoRecetvefromclient(client©02)Recetvefromclient(client©01)Recetvefromclient(client©02)图4-2.服务器显示客户端,服务器接受数据并处理❸00knight@knight-Aspire-4750:~kntght@knight-Asptre-4750:gcc-oeLtentclientkntghtgiknight-Asptre-47501~5*/clientUsager./client<IPaddress>kntghtgiknight-Aspire-47501~5*/client127.9.@*1ServerMessage:Welcometoryserver*Inputyourname:cttentQOlInputyournessage(naxr1000):woshtkntghtTheconvinceofyourmessageithgtnkthsowInputyournessage(naxrlOOO):ntrenshtTheconvinceofyourmessage:thsnertnsowInputyournessage(naxr1060)图4-3图4-3客户1发送数据并得到回显©◎蓟knight@knight-Aspire-475D:~knight®knight-A5pi「日-4750*/client127.0.@*LServerMessage:Wetcometomyserver*Inputyourname:cttent902Inputyournessage(naxr1000):nthaomaTheconvinceofyourmessage:amoahinInputyournessage(naxr1000):ntzhtdaoTheconvinceofyourmessage:oadihztnInputyournessage(naxr1060)图4-4图4-4.客户2发送信息给服务器,并接受服务器处理后的数据,在屏幕输出❷鲁国knighc@knight-Aspire-475D:~kntght@knight-Aspire-4759:gcc-oclientclientkntght@knight-Aspire-47591./clientUsager./client<IPaddress>kntght|gknight-Aspire-47591~5*/client127*0.0.1ServerMessage:Welcometonyserver*Inputyourname:cttentQOlInputyournessage(naxr1000):woshiknightTheconvinceofyourmessageithginkthsowInputyournessage(naxr1000):ntrenshtTheconvinceofyourmessage:thsnertnsowInputyournessage(naxr1000):ACkntght|gknight-Aspire-47501图4-5.客户端可通过输入ctrl+c来释放连接,服务器端给予应答及释放连接,并再次在屏幕显示客户端数据.建立套接字并在某一约定端口上等待接收客户请求;1使用socket。创建套接字2将创建的套接字绑定在指定的地址结构。3Listen()函数设置套接字为监听模式,使服务器进入被动打开状态,等待客户请求.当接收到来自客户端的服务请求后:建立一新线程来处理,同时主线程继续等待其他客户连接。当新线程处理完成后,关闭新线程与客户的通信链路并终止新线程。1服务器主线程接受客户请求,建立连接并fork新的线程,调用savedata()线程安全函数,调用create_once()函数产生TSD关键字,再与该客户通信。主线程继续接受下一个客户请求。2接受客户发来的数据按先后顺序存在数据缓冲区。.关闭服务器。以上过程如图4-6主缭呈工作线程主缭呈工作线程图4-6附录:源程序代码:〃所需头文件#include<pthread.h>#include<unistd.h>#include<stdio.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>#include<netdb.h>#include<string.h>#include<stdlib.h>#definePORT1234#defineBACKLOG2#defineMAXCHARSIZE1000voidpro_client(intconnectfd,structsockaddr_inclient);void*exec_thread(void*arg);voidsave_data(char*recvbuf,intlen,char*cli_data);structARG{intconnfd;structsockaddr_inclient;};structARG*arg;intmain(void){intlistenfd,connectfd;structsockaddr_inserver,client;intsin_size;intopt=SO_REUSEADDR;pthread_ttid;sin_size=sizeof(structsockaddr_in);if((listenfd=socket(AF_INET,SOCK_STREAM,0))==-1){perror("Createsocketfailed.");exit(-1);}setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));bzero(&server,sizeof(server));server.sin_family=AF_INET;server.sin_port=htons(PORT);server.sin_addr.s_addr=htonl(INADDR_ANY);if(bind(listenfd,(structsockaddr*)&server,sizeof(structsockaddr))==-1){perror("Binderror.");exit(-1);}if(listen(listenfd,BACKLOG)==-1){perror("Listenerror.");exit(-1);}while⑴{if((connectfd=accept(listenfd,(structsockaddr*)&client,&sin_size))==-1){perror("Accepterror.");exit(-1);}arg=(structARG*)malloc(sizeof(structARG));arg->connfd=connectfd;memcpy((void*)&arg->client,&client,sizeof(client));if(pthread_create(&tid,NULL,start_routine,(void*)arg)){perror("Pthread_createerror.\n");exit(-1);}}close(listenfd);}//TSD关键字变量keystaticpthread_key_tkey;〃变量once并赋值staticpthread_once_tonce=PTHREAD_ONCE_INIT;//ST_DATA结构,用于存储TSDstructDATA_THR{intindex;};〃析构函数key_destro(),在线程退出时该析构函数将被调用,,以释放为TSD分配的空间staticvoidkey_destroy(void*buf){free(buf);}〃定义函数,以产生TSD关键字staticvoidbuffer_key_alloc(){pthread_key_create(&key,key_destroy);}〃定义函数save_data()voidsave_data(char*recvbuf,intlen,char*cli_data){structDATA_THR*data;pthread_once(&once,buffer_key_alloc);if((data=(structDATA_THR*)pthread_getspecific(key))==NULL){data=(structDATA_THR*)calloc(1,sizeof(structDATA_THR));pthread_setspecific(key,data);data->index=0;}inti;for(i=0;i<len;i++)cli_data[data->index++]=recvbuf[i];cli_data[data->index]='\0';//■■■■■■voidpro_client(intconnectfd,structsockaddr_inclient){charrecvbuf[MAXCHARSIZE];charsendbuf[MAXCHARSIZE];charclient_name[MAXCHARSIZE];charclient_data[5000];intrecvlen,i;printf("Yougetaconnectfrom%s\n",inet_ntoa(client.sin_addr));send(connectfd,"Welcometomyserver.\n",22,0);recvlen=recv(connectfd,client_name,MAXCHARSIZE,0);if(recvlen==0){close(connectfd);printf("Clientdisconnected.\n");return;elseif(recvlen<0){close(connectfd);printf("Connectbroked.\n");return;}client_name[recvlen]='\0';printf("Clientnameis%s.\n",client_name);bzero(recvbuf,1000);while(recvlen=recv(connectfd,recvbuf,MAXCHARSIZE,0)){save_data(recvbuf,recvlen,client_data);recvbuf[recvlen]='\0';printf("Receivefromclient(%s)message:%s\n",client_name,recvbuf);for(i=0;i<recvlen;i++)sendbuf[i]=recvbuf[recvlen-i-1];send(connectfd,sendbuf,strlen(sendbuf),0);bzero(recvbuf,1000);printf("Client:%sdisconnected.User'sdata:%s\n",client_name,client_data);close(connectfd);〃实现线程的执行函数void*exec_thread(void*arg){structARG*info;info=(structARG*)arg;pro_client(info->connfd,info->client);free(arg);pthread_exit(NULL);}客户端程序:#include<unistd.h>#include<sys/socket.h>#include<netinet/in.h>#include<netdb.h>#include<string.h>#include<stdlib.h>#include<stdio.h>#definePORT1234#defineMAXDATASIZE1000;intmain(intargc,char*argv[])intfd,numbytes;charbuf[1000];structhostent*he;structsockaddr_inserver;inti=1;if(argc!=2){printf("Usage:%s<IPaddress〉\n",argv[0]);exit(-1);}〃获得服务器的地址信息if((he=gethostbyname(argv[1]))==NULL)perror("gethostbynameerror.");exit(-1);}if((fd=socket(AF_INET,SOCK_STREAM,0))==-1){perror("Createsocketfailed.");exit⑴;}bzero(&server,sizeof(server));server.sin_family=AF_INET;server.sin_port=htons(PORT);server.sin_addr=*((structin_addr*)he->h_addr);if(connect(fd,(structsockaddr*)&server,sizeof(structsockaddr))==-1){perror("Binderror.");exit⑴;}if((numbytes=recv(fd,buf,1000,0))==-1){perror("recverror.");exit⑴;}buf[numbytes]='\0';printf("ServerMessage:%s\n",buf);printf("Inputyourname:");scanf("%s",buf);if((numbytes=send(fd,buf,strlen(buf),0))==-1){perror("Senderror.");exit⑴;}bzero(buf,1000);while(i){printf("Inputyourmessage(max:1000):");scanf("%s",buf);if(strlen(buf)<1)i=0;if((numbytes=send(fd,buf,strlen(buf),0))==-1){perror("Senderror.");exit⑴;}bzero(buf,1000);if((n

温馨提示

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

评论

0/150

提交评论