实验五、多线程并发服务器编程

2018-12-29 22:56

实验五、多线程并发服务器编程

一、实验目的

1、学习Linux操作系统的多线程的基本概念以及进程与线程的区别; 2、掌握编写多线程程序的一般方法;

3、熟悉多线程并发服务器的设计思路,以及多线程程序的编译链接方法。

二、实验内容

线程(thread)技术早在60年代就被提出,但真正应用多线程到操作系统中去,是在80年代中期,solaris是这方面的佼佼者。现在多线程技术已经被许多操作系统所支持,包括Windows/NT以及Unix/Linux。

为什么有了进程的概念后,还要再引入线程呢?使用多线程到底有哪些好处?什么的系统应该选用多线程?使用多线程的理由之一是和进程相比,它是一种非常\节俭\的多任务操作方式。在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种\昂贵\的多任务工作方式。而运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,而且线程间彼此切换所需的时间也远远小于进程间切换所需要的时间。据统计一个进程的开销大约是一个线程开销的30倍左右。

使用多线程的理由之二是线程间方便的通信机制。对不同进程来说,它们具有独立的数据空间,要进行数据的传递只能通过通信的方式进行,这种方式不仅费时,而且很不方便。线程则不然,由于同一进程下的线程之间共享数据空间,所以一个线程的数据可以直接为其它线程所用,这不仅快捷,而且方便。当然,数据的共享也带来其他一些问题,有的变量不能同时被两个线程所修改,有的子程序中声明为static的数据更有可能给多线程程序带来灾难性的打击,这些正是编写多线程程序时最需要注意的地方。

1、编写一个最简单的多线程程序 请仔细运行、分析下列程序,指出多进程和多线程如何区分?何谓父线程和子线程?当父线程终止会导致子线程发生何种情况?

/***************************************************************** 文件名:pthread_example.c

演示了pthread_create函数创建子线程的使用

*******************************************************************/ #include

#include //创建多线程

void childThread();

int main() { int i = 0; pthread_t id;

pthread_create(&id,NULL,childThread,NULL); printf(\点击回车键结束运行\\n\ getchar(); }

void childThread() { int i; for(i=0;;) { printf(\ sleep(1); } }

编译链接多线程程序需要用到特殊的库文件libthread.so,而我们在以前的实验中的编译链接程序的方式使用的是标准库函数,不需要特别指定。因此编译链接多线程的程序时必须使用 –l 选项,该选项后面直接跟库文件名称,但要去掉lib和后缀名,即 –lthread 。注意-l是lib的首字母。例如如果需要用到数学函数库 libm.so则编译链接程序时需要使用选项 –lm 。 按以前实验方式编译该程序发现错误,图1中红色部分为错误信息,该信息表明链接程序未找到函数pthread_create的实现。图2为编译正确的结果显示。

图1、未使用-lpthread选项链接错误

图2、正确使用-lpthread选项编译链接结果

2、多线程并发服务器编程

类似于多进程服务器编程,本实验的多线程并发服务器也分为两部分程序:服务器程序和客户端程序。其中客户端部分和实验一中的客户端部分是一致的,在本实验中我们作了简化;请注意本实验中的客户端只是为了测试并发服务器的功能,它们本身并不属于多线程并发服务器的内容。服务器部分实现了多线程的功能,父线程不断地(for循环)等待客户端的连接,一旦有客户端连接服务器,服务器则创建(pthread_create)一个子线程用于该客户端的接收数据处理。在验证结果阶段可以同时启动多个客户端,注意服务器只需要启动一次。

显而易见的是随着客户端数量的增加,服务器子线程的数量也将线性增加,这必将加重服务器硬件资源(内存)的消耗,最终可导致服务器硬件资源耗尽而崩溃。但与实验六中多进程并发服务器相比,对同等数量的多线程和多进程程序而言,多线程程序对内存的需求明显低于多进程程序。

本次实验中的客户端程序作了更多的简化,采用单文件方式。客户端部分未用到多线程,其编译链接方法与以前的实验一致。服务器部分仍然采用多文件方式,因此在编译运行时要用到多个C文件,注意编译时要加上 –lthread选项。

分析、运行下列代码,建议由两位同学分别运行服务器和客户端,然后再转换角色分析程序。

1)客户端程序源码

/******************************************************************************

文件名:TCPSimpleClient.c

描述:一个简单的TCP客户端例子,发送hello world给服务器,并接收服务器返回 ******************************************************************************/ #include #include #include #include #include #include #include

int main(int argc, char *argv[]) { if (argc != 3) { printf(\使用方式必须为:$>命令 服务器地址 服务器端口号\\n\ return 1; }

char *ip = argv[1]; char *port = argv[2]; int cs = socket ( AF_INET, SOCK_STREAM, IPPROTO_TCP); if (cs < 0) { printf(\创建套接字失败\\n\ return -1; } struct sockaddr_in serv; memset (&serv, 0, sizeof (serv) ); serv.sin_port = htons(atoi(port));

inet_pton(AF_INET,ip, &serv.sin_addr.s_addr); serv.sin_family = AF_INET;

printf(\开始与服务器建立连接!\\n\ if(connect (cs, (struct sockaddr *)&serv, sizeof(serv))<0) { printf(\连接失败!\\n\ return -1; }

printf(\连接成功!\\n\

char buf[100] = \ send(cs, buf, strlen(buf), 0);

memset(buf,0,sizeof(buf)); recv(cs,buf,sizeof(buf)-1,0); printf(\服务器返回信息:%s\\n\ close(cs); return 0; }

2)服务器源码 服务器源码涉及四个C文件和一个头文件,各文件内容如下:

/************************************************************************* 文件名:Practical.h

***************************************************************************/ #ifndef PRACTICAL_H_ #define PRACTICAL_H_

#include #include

#include

void DieWithUserMessage(const char *msg, const char *detail); void DieWithSystemMessage(const char *msg);

void PrintSocketAddress(const struct sockaddr *address, FILE *stream);

bool SockAddrsEqual(const struct sockaddr *addr1, const struct sockaddr *addr2); int SetupTCPServerSocket(const char *service); int AcceptTCPConnection(int servSock); void HandleTCPClient(int clntSocket);

int SetupTCPClientSocket(const char *server, const char *service);

enum sizeConstants {

MAXSTRINGLENGTH = 128, BUFSIZE = 512, };

#endif // PRACTICAL_H_

/**************************************************************************** 文件名:msg.c

*****************************************************************************/

#include #include

void DieWithUserMessage(const char *msg, const char *detail) { fputs(msg, stderr); fputs(\ fputs(detail, stderr); fputc('\\n', stderr); exit(1);


实验五、多线程并发服务器编程.doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:用友ERP供应链管理系统实验报告

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: