《网络开发与应用》实验指导书 哈尔滨工业大学软件学院 《网络开发与应用》实验指导书 李全龙 宋艳艳 2005年10月 1 《网络开发与应用》实验指导书 前 言 《网络开发与应用》课程是计算机科学与技术专业的重要专业课程之一。随 着互联网的蓬勃发展,计算机网络在社会经济和人们生活中占据着越来越重要的 地位,成为经济发展和现代生活不可缺少的一部分,掌握计算机网络知识成为社 会对人才的基本要求。作为培养高素质人才的高校,为了满足社会对人才的需求, 给《网络开发与应用》课程的教学提出了新的更高的要求。 计算机网络是一门实践性很强的课程,实践环节在教学过程中起着越来越重 要的作用。通过实验不仅可以加深学生对网络原理的理解和掌握,更重要的是培 养学生在网络方面的应用、管理和维护能力,并根据所学知识分析解决网络应用 过程中出现的问题。 希望同学们在使用本实验指导书及进行实验的过程中,能够帮助我们不断地 发现问题,并提出建议,使《网络开发与应用》成为具有世界一流水平的课程。 本学期授课教师为李全龙老师,参与网络课程助教环节的教师为宋艳艳同学。 2 《网络开发与应用》实验指导书 实验要求 计算机网络是现代信息社会最重要的基础设施之一。在过去十几年里得到了 迅速的发展和应用。《网络开发与应用》课程实验的目的是为了使学生在课程学 习的同时,通过在一个计算机网络环境中的实际操作,对现代计算机网络的基本 功能有一个初步的了解;通过实现一个客户服务器程序,掌握Socket编程框架, 熟悉典型的Socket系统调用;通过一个典型的并发服务器的设计与实现,了解计 算机网络的服务器程序开发;还提供了一些设计实验以使同学们的兴趣进一步提 高。总之,通过上述实验环节,使学生加深了解和更好地掌握《网络开发与应用》 课程教学大纲要求的内容。 在《网络开发与应用》的课程实验过程中,要求学生做到: (1)预习实验指导书有关部分,认真做好实验内容的准备,就实验可能出 现情况提前做出思考和分析。 (2)仔细观察上机和上网操作时出现的各种现象,记录主要情况,做出必 要说明和分析。 (3)认真书写实验报告。实验报告包括实验目的和要求,实验情况及其分 析。对需要编程的实验,写出程序设计说明,给出源程序框图和清单。 (4)遵守机房纪律,服从辅导教师指挥,爱护实验设备。 (5)实验课程不迟到。如有事不能出席,所缺实验一般不补。 实验的验收将分为两个部分。第一部分是上机操作,包括检查程序运行和即 时提问。第二部分是提交书面的实验报告。此外,网络实验采用当堂检查方式, 每个实验都应当在规定的时间内完成并检查通过,过期视为未完成该实验,不计 成绩。以避免集中检查方式产生的诸多不良问题,希望同学们抓紧时间,合理安 排,认真完成。 3 《网络开发与应用》实验指导书 实验评分标准 一、课堂表现(10分) 1.出勤情况(按时,迟到,早退,缺席) 2.是否遵守课堂纪律 二、实验结果(50分) 1.当堂按时完成(10分) 2.独立完成(10分),(和同学协商完成,在老师帮助下完成) 3.结果正确无误(10分) 4.功能齐全,界面美观,具有较好演示效果(10分) 5.在源程序中有必要的注释和说明(5分) 6.程序文档齐全(5分) 三、实验报告(40分) 1.对预习要求的回答(10分) 2.实验过程中遇到的问题如何解决的(10分) 3.实验的体会(10分) 4.思考题(10分) 4 《网络开发与应用》实验指导书 实验1熟悉socket编程和客户服务器编程 实验目的 1. 更加熟悉VC开发环境。 2. 掌握socket编程框架。 3. 熟悉典型的socket系统调用和相关函数等,为后面几个实验奠定基础。 实验要求 一、对学生要求: 1.掌握网络通信原理。 2.掌握socket通信机制。 3.掌握使用socket的编程思想。 4.根据算法编写与实验内容相关的程序,要求该程序能实现同步通信功能。 二、对实验指导教师要求: 1.熟悉VC语言。 2.熟悉socket网络程序设计。 3.编写并运行该题目程序代码,具有该题目的参考答案。 4.深刻理解题目内涵,能够清晰描述问题,掌握该题目涉及的知识点,指 导学生实验时需要注意的问题。 实验内容 在VC开发环境下,使用C语言,应用socket实现网络通信。 实验结果要求 服务器端出现两个窗口,一个是监听器窗口(此窗口显示客户端的IP地址), 另一个是服务器端对话窗口(显示客户端发送来的消息)。客户端出现带按钮的 消息发送窗口,用户就通过此对话窗口与服务器对话。程序结果窗口如图所示: 5 《网络开发与应用》实验指导书 6 《网络开发与应用》实验指导书 编程提示 完整的客户服务器端程序的作用是先建立一个服务器程序并启动监听线程, 监听线程的窗口(Server Listener)中显示出客户机连接和断开的情况。当一个 客户机程序启动并向服务器提出请求时,客户机窗口被创建,这个窗口中包含3 个按钮,当用户点击某个按钮时,程序读取服务器端的相应信息并显示在窗口中; 同时在服务器端,为响应客户机的请求,一个新的线程被创建和启动,建立窗口 Answer Client n,其中n是客户机的连接序号,这个线程将监听客户机端所做的操 作并将有关信息在窗口中显示出来。当用户结束对服务器端的信息查询时,客户 机窗口被关闭,相应地,与之通信的服务器进程也结束。所有这些客户机的连接 和断开信息都将在监听进程的窗口中显示出来。 思考题 1.典型的通信发生在一个客户端和一个服务器端之间,这样的通信对应着 几个套接字?这些套接字在客户和服务器之间建立的连接是单向数据传送还是 双向数据传送? 2.如何理解套接字中端口的含义? 7 《网络开发与应用》实验指导书 实验2 循环服务器 实验目的 1. 熟悉循环服务器的概念。 2. 掌握UDP循环服务器的实现。 3. 掌握TCP循环服务器的实现。 实验要求 一、对学生要求: 1. 掌握UDP循环服务器原理。 2. 掌握TCP循环服务器原理。 3.根据算法编写与实验内容相关的程序,要求该程序能实现循环服务器功 能。 二、对实验指导教师要求: 1.熟悉循环服务器原理。 2.编写并运行该题目程序代码,具有该题目的参考答案。 3.深刻理解题目内涵,能够清晰描述问题,掌握该题目涉及的知识点,指 导学生实验时需要注意的问题。 实验内容 在VC开发环境下,使用C语言,编程实现一个循环服务器。该程序等候客户 连接,一旦连接则显示客户的地址,然后接收来自该客户的信息(字符串)。每 当收到一个字符串,则显示该字符串,并将字符串反转,再将反转的字符发回客 户。之后,继续等待接收该客户的信息直至该客户关闭连接。完成与该客户交互 后,服务器开始等待下一客户,并重复上述过程。 例如,客户连接到循环服务器上之后,并且发送了一串字符“abc”。在循环 服务器端先显示客户的地址,然后显示这个客户信息“abc”,服务器将字符反转 变成“cba”之后发会给客户。直到该客户关闭连接为止,服务器开始为下一个 客户服务。一直重复这个过程。 8 《网络开发与应用》实验指导书 思考题 1.什么叫循环服务器?UDP循环服务器和TCP循环服务器的区别是什么? 2.什么情况下,UDP循环服务器对于客户机的请求不能满足? 9 《网络开发与应用》实验指导书 实验3 并发服务器(1) 实验目的 1. 熟悉并发服务器的概念。 2. 熟悉多协议服务器的概念。 3. 掌握UDP并发服务器的实现。 4. 掌握TCP并发服务器的实现。 实验要求 一、对学生要求: 1. 掌握UDP并发服务器原理。 2. 掌握TCP并发服务器原理。 3. 掌握使用TCP Sockets构建客户服务器网络。 4. 学会构建并发服务器。 5. 根据算法编写与实验内容相关的程序,要求该程序能实现并发服务器功 能。 二、对实验指导教师要求: 1. 熟悉并发服务器原理。 2. 编写并运行该题目程序代码,具有该题目的参考答案。 3. 深刻理解题目内涵,能够清晰描述问题,掌握该题目涉及的知识点,指 导学生实验时需要注意的问题。 实验内容 在UNIX/KDE开发环境下,使用C语言,实现一个ECHO服务器。扩展程序 功能,实现一个既可以支持UDP服务,同时又可以支持TCP服务的多协议ECHO 服务器。 提示:考虑文件TCPmechod.c,它含有实现ECHO服务的一个单进程服务器的代码: /*TCPmechod.c - main,echo*/ #include <sys/types.h> #include<sys/socket.h> #include<sys/time.h> #include<netinet/in.h> #include<unistd.h> #include<string.h> #include<stdio.h> #define QLEN 5 /*maximum connection queue length */ 10 《网络开发与应用》实验指导书 #define BUFSIZE 4096 extern int errno; int errexit(const char * format,…..); int passiveTCP(const char *service, int qlen); int echo(int fd); /*――――――――――――――――――――――――――――――― *main —— Concurrent TCP server for ECHO service *――――――――――――――――――――――――――――――― */ int main(int argc, char * argv[]) { char *service =”echo”; /*service name or port number */ struct sockadder_in fsin; /*the from address of a client */ int msock; /*master server socket */ fd_set rfds; /*read file descriptor set */ fd_set afds; /*active file descriptor set */ int alen; /*from-address length */ int fd,nfds; swith(argc){ case 1: break; case 2: service=argv[1]; break; default: errexit(“usage:TCPmethod[port]\n”); } msock=passiveTCP(service,QLEN); nfds=getdtablesize(); FD_ZERO(&afds); FD_SET(mscok,&afds); While(1){ memcpy(&rfds,&afds,sizeof(rfds)); if(select(nfds,&rfds,(fd_set *)0,( fd_set *)0,(struct timeval *)0)<0) errexit(“select:%s\n”,strerror(errno)); if(FD_ISSET(msock,&rfds)){ int ssock; alen=sizeof(fsin); ssock=accept(msock,(struct sockaddr *)&fsin,&alen); if(sock<0) errexit(“accept:%s\n”,strerror(errno)); FD_SET(ssock,&afds); } 11 《网络开发与应用》实验指导书 for(fd=0;fd<nfds;++fd) if(fd!=msock&&FD_ISSET(fd,&rfds)) if(echo(fd)==0){ (void)close(fd); } } } /*――――――――――――――――――――――――――――――――― *echo - echo one buffer of data, returning byte count *―――――――――――――――――――――――――――――――――― */ int echo(int fd) { char buf(BUFSIZ); int cc; cc=read(fd,buf,sizeof buf); if(cc<0) errexit("echo read:%s\n",strerror(errno)); if(cc&&write(fd,buf,cc)<0) errexit("echo write:%s\n",strerroe(errno)); return cc; 程序说明 类似多进程实现中的主服务器,单进程服务器一开始就在知名端口上打开一 个被动插口。它使用FD_ZERO和FD_SET创建一个比特向量(bit vector),对应 于服务器希望测试的描述符。然后服务器进入一个无限循环,在循环中它调用 select,等待一个或多个描述符准备就绪。 如果主描述符(master descriptor)准备就绪,服务器就调用accept获取一个 新的连接。它将新连接用的描述符加入到它所管理的那些描述符中,并继续等待 更多描述符的动作。如果一个从描述符(slave descriptor)准备就绪,服务器就 调用过程echo,该过程再调用read从这一连接获取数据,并调用write将数据发回 客户机。如果其中某个从描述符报告了文件结束(end-of-file)的条件,服务 器就关闭该描述符,并使用宏FD_CLR从select使用的那组描述符中删除它。 思考题 1.什么是并发服务器? 2.TCP并发服务器解决了TCP循环服务器的什么问题?同时又带来了什么 问题? 12 《网络开发与应用》实验指导书 实验4 并发服务器(2) 实验目的 1. 熟悉并发服务器的实现原理。 2. 熟悉多服务服务器的基本原理。 3. 学会使用Pthread库。 4. 熟悉mutual exclusion的概念。 实验要求 一、对学生要求: 1. 熟悉Pthread库。 2. 熟悉mutual exclusion。 3. 根据算法编写与实验内容相关的程序,要求该程序能实现并发服务器功 能。 二、对实验指导教师要求: 1. 熟悉并发服务器和POSIX线程。 2. 编写并运行该题目程序代码,具有该题目的参考答案。 3. 深刻理解题目内涵,能够清晰描述问题,掌握该题目涉及的知识点,指 导学生实验时需要注意的问题。 实验内容 修改实验3使之能提供ECHO、TIME和DAYTIME服务,即在多协议单服务服 务器的基础上实现多协议多服务服务器(超级服务器)。 提示1:考虑UDPtimed.c中含有一个循环的、无连接的TIME服务器所用的代码 /*UDPtimed.c — main*/ #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<stdio.h> #include<time.h> #include<string.h> extern int errno; int passiveUDP(const char * service); 13 《网络开发与应用》实验指导书 int errexit(const char * format,…); #define UNIXEPOCH 2208988800 /*UNIX epoch, int UCT secs */ /*-------------------------------------------------------------------------------------------------------------------- *main — Iterative UDP server for TIME service *--------------------------------------------------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { struct sockaddr-in fsin; /*the from address of a client */ char *service=”time”; /*service name or port number */ char buf[1]; /*”input” buffer; any size>0 */ int sock; /*server socket */ time-t now; /*current time */ int alen; /*from-address length */ switch(argc){ case 1: break; case 2: service=argv[1]; break; default: errexit(“usage: UDPtimed[port]\n”); } sock=passiveUDP(service); while(1){ alen=sizeof(fsin); if(recvfrom(sock,buf,sizeof(buf),0,(struct sockaddr *)&fsin,&alen)<0) errexit(“recvfrom: %s \n”,strerror(errno)); (void) time(&now); Now=htonl((u_long)(now+UNIXEPOCH)); (void) sendto(sock,(char *)&now, sizeof(now), 0, (struct sockaddr *)&fsin,sizeof(fsin)); } } 程序说明 与任何服务器类似,UDPtimed进程必须永远运行着。因此,代码主体含有一 个无限的循环,该循环每次接收一个请求,计算当前时间,然后给发送请求的用 户机返回响应。 代码含有几处细节。分析完参数后,UDPtimed调用passiveUDP为TIME服务 创建一个被动插口。然后它便进入循环。TIME协议指明,客户机可发送任意一 个数据报作为请求。由于服务器不解释数据报的内容,数据报可以是任何长度, 14 《网络开发与应用》实验指导书 并可含有任意值。本例实现使用从recvfrom读取下一个数据报。recvfrom将入数 据报放到缓冲区buf中,并将发送数据报的客户机的端点地址放到结构fsin中。由 于它不必查看数据,实现只使用了单个字符的缓冲区。如果数据报含有的数据多 于一个字节,recvfrom就丢弃所有剩余的字节。 UDPtimed使用UNIX系统例程time获得当前时间。因为UNIX使用一个32比特 整数表示时间,时间是从1970年1月1日零时开始计算。从UNIX获得时间后, UDPtimed必须将它转换为用Internet纪元(epoch)测量的时间值,并用网络字节 序存放结果。为完成转换,它增加了一个常量UNIXEPOCH,该常量值定义为 2208988800,即为Internet计时起始值与UNIX计时起始值间相差的秒数。然后它 调用sendto将结果传回客户机。sendto使用结构fsin中的端点地址作为目的地址 (即它使用了发送数据报的客户机的地址)。 提示2:考虑TCPdaytimed.c中含有一个循环的、面向连接的DAYTIME服务器的例子代码 /*TCPdaytimed.c — main*/ #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<unistd.h> #include<stdio.h> #include<string.h> extern int errno; int errexit(const char * format,…); int TCPdaytimed(int fd); int passiveTCP(const char * service,int qlen); #define QLEN 5 /*-------------------------------------------------------------------------------------------------------------------- *main — Iterative TCP server for DAYTIME service *--------------------------------------------------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { struct sockaddr-in fsin; /*the from address of a client */ char *service=”daytime”; /*service name or port number */ int msock,ssock; /*master&slave sockets */ int alen; /*from-address length */ switch(argc){ case 1: break; 15 《网络开发与应用》实验指导书 case 2: service=argv[1]; break; default: errexit(“usage: TCPdaytimed[port]\n”); } msock=passiveTCP(service,QLEN); while(1){ ssock=accept(msock,(struct sockaddr *)&fsin,&alen); if(ssock<0) errexit(“accept failed: %s\n”,strerror(errno)); (void) TCPdaytimed(ssock); (void) close(ssock); } } /*-------------------------------------------------------------------------------------------------------------------- *TCPdaytimed — do TCP DAYTIME protocol *--------------------------------------------------------------------------------------------------------------------- */ int TCPdaytimed(int fd) { char *pts; /*pointer to time string */ time-t now; /*current time */ char *ctime(); (void) time (&now); pts=ctime(&now); (void)write(fd,pts,strlen(pts)); return 0; } 程序说明 类似提示1所描述的循环的无连接的服务器,这种循环的、面向连接的服务 器也必须永远运行。在创建了一个在知名端口上监听的插口后,服务器就进入一 个无限循环,在循环中接受和处理连接。 服务器的代码相当短,这是因为passiveTCP的调用隐藏了插口分配和邦定的 细节。调用passiveTCP创建了与DAYTIME服务所用知名端口相关联的主插口。 第二个参数指名主插口的连接请求队列长度是QLEN,从而允许系统在忙于回答 某个客户机的连接请求时,将来自其他QLEN个客户机的连接请求进行排队。 创建主插口后,服务器的主程序将进入无限循环。在每次循环中,服务器调 用accept从主插口获得下一个连接。为防止服务器在等待来自客户机的连接时耗 费资源,accept调用将一直阻塞,直到一个连接到达。当一连接请求到达时,TCP 16 《网络开发与应用》实验指导书 协议软件为建立连接而忙于进行三方握手。一旦握手完成,并且系统已为入连接 分配了一个新插口,accept调用将返回新插口的描述符,并允许服务器继续执行。 如果没有连接请求达到,服务器进程将在accept调用中一直保持阻塞状态。 每次在新的连接到达时,服务器就调用过程TCPdaytimed对它进行处理。 TCPdaytimed中的代码以UNIX函数time和ctime的调用为核心。过程time返回一个 32比特整数,以此给出当前时间,它是自UNIX纪元(计时起始值)以来所经过 的秒数。UNIX库函数ctime带来一个整型参数,该参数指明一个用UNIX纪元所 经过的秒数表示的时间。该函数返回一个含有格式化的时间和日期的ASCII字符 串的地址,便于人们理解。一旦服务器获得用ASCII字符串表示的时间和日期, 它就调用write将字符串通过TCP连接发送给客户机。 调用TCPtimed一旦返回,主程序就继续执行循环,在此调用accept。而accept 调用在另一个请求到达前将使服务器阻塞。 思考题 1.一般在什么情况下使用UDP并发服务器? 2.TCP并发服务器和UDP并发服务器的区别是什么? 17 《网络开发与应用》实验指导书 实验5 设计并实现简单的Web服务器 实验目的 1. 了解Web服务器的概念及其功能。 2. 掌握构建Web服务器的一般方法。 3. 了解Web服务器常见的问题与解决方法。 4. 理解Web服务的基本概念、特征、实质与提供的主要服务。 5. 掌握Web服务器提供的基本服务FTP、WWW的配置与使用方法。 实验要求 一、对学生要求: 1. 熟悉掌握Web服务器的功能。 2. 熟悉掌握Web服务器的建立过程。 二、对实验指导教师要求: 1. 熟悉Web服务器的安装及配置。 2. 熟练创建远程管理Web站点 实验内容 在VC开发环境下,使用C语言,设计并实现简单的Web服务器。本实验建议 采用Word进行简单HTML文档的处理。要求学生在预习时开发个人的Web站点, 在实验过程中实时安装到创建的Web服务器的网页发布目录中,要求只要别人知 道你的服务器IP地址,就可以进行HTTP浏览和Web 服务器测试。同时你的Web 服务器能够识别简单的请求报文、响应保文,例如GET、HEAD等。 对已经安装好的个人Web服务器进行测试的方法有两种: 第一种方法:启动浏览器(IE或Communicator皆可),在地址栏中输入一个 测试用的IP:HTTP://127.0.0.1 或 HTTP://LOCALHOST 自测地址是一个通用的IP地址,任何一台安装了TCP/IP协议服务软件的主机 都可以使用该地址对安装在本地主机(local host)运行的服务器程序进行测试。 必须注意的是,这里的测试虽然是在一台主机上完成的,但测试任务仍然是在 B/S(浏览器/服务器)模式下完成的。 测试结果当然是一个默认的主页 (home page),由于一般的Web服务器都会 在发布主目录安排若干所谓默认网页,一旦用户请求的URL中只有主机IP或主机 域名(也就是一个相对的URL)时,服务器将自动以默认主页应答。一般常用的 默认主页名有: index.htm、index.html、default.htm //HTML(静态)网页 index.php、index.php3、index.asp、index.jsp //动态网页 18 《网络开发与应用》实验指导书 第二种方法,使用本地主机的IP地址进行测试。由于127.0.0.1的测试只能在 本地主机上进行,如果希望从网络上其他主机上进行测试,则需要知晓服务器的 IP地址(当然也可以使用主机域名进行,但鉴于在实验环境下难以建立DNS服务, 建议先采用IP地址进行实验),在Windows环境下常用的IP测试软件有GUI界面的 Winipcfg.exe和字符界面的Ipconfig.exe。使用Winipcfg.exe检查IP地址的结果如图 4所示。 查出IP地址之后,可以通知其他主机上的实验伙伴,在其主机的浏览器地址 中输入本地主机的IP地址,这时,本地主机上的Web服务器就会把默认的主页发 送出去。当然,用户也可以在本地主机的浏览器地址中输入本机的IP地址,只是 其测试效果与使用127.0.0.1比较,并没有什么区别。 从这个时候起,读者本人已经可以从一个万维网信息的消费者转变为万维网 信息的发布者,所以,建议读者将下列短文输入到一个文本文件(可以用Windows 下的记事本,这个最简单的文本编辑器): Congratulation! From now on , YOU can choose the character such as a WWW consumer, a WWW publisher or the BOTH. 用户在编辑完成后用test.htm的文件名存入你个人Web服务器的发布主目录 下,然后用浏览器进行访问,如: HTTP://127.0.0.1/TEST.HTM 思考题 1.如何提高Web服务器的安全性? 2.如何只允许授权用户访问站点? 19