参加段景山老师“教改班”的体会

大三上学期期末选课时,看到网络软件设计这门课,感觉比较有趣,虽然是选修课,还是给予了相当多的选课权重。

之前对网络通信的认识仅仅来源于计算机网络和TCP/IP的课程,也只是听说过有“Socket”这个东西,但是计算机网络课程有点“通识”的味道,从宏观的角度描述整个网络体系结构,从物理层一直讲到传输层、应用层,稍微有点深入的是路由算法——距离矢量、链路状态等,其实当时学过这门课还是不了解到底是学的什么东西,概念太多,学得又很泛;而TCP/IP课程建立在计算机网络课程的基础上,主要放在对网络层和传输层的讲解上,稍微实用了一些,至少学完之后,知道了什么是IP地址、为什么要有IP地址、IP地址的规划等,以及对各种网络协议有了较深入的认识,也知道了路由器到底是如何工作的。但是课程的内容很多,专业性又强,给我的感觉还是比较枯燥的。

而网络软件设计这门课,让我认识了网络软件的设计方法,理解了socket通信的原理,甚至学习了软件开发的流程,从撰写需求分析到设计软件模块、编码、调试等,这对于我们这些非计算机专业却又想尝试一下软件开发的通信学子而言无疑是一个极好的机会。我觉得这门课是继C语言、软件技术基础之后又一门非常值得去学习的课程。

下面就基于教改班的6个项目做个简单的总结。

第一个项目,回音壁。实现的功能就是发送方发一串数据给接受方,接受方像一个墙壁一样把数据“弹回来”。然后通过这个简单的程序可以估计网络传输时延、带宽等参数。作为第一个项目,它并不难,就是在基本的通信流程下再加上计算时延的方法。一开始我在寝室里测试,发现回环地址几乎没有时延(因为根本就没有上物理链路),即使是两台电脑,时延也非常小;但是如果是无线,时延就会比较明显。开始我用GetTickCount()函数测量,精度不够,后来改用QueryPerformanceFrequency()函数和QueryPerformanceCounter()函数。这个项目引领我们开始网络软件的设计之路,后面我们将在它的基础上实现各种复杂又有趣的功能。

第二个项目:简单的聊天程序。实现的功能就是运行客户端和服务器端程序的双方可以聊天。基本的要求是实现双方“你说一句,我说一句”的功能,即一方在发完一个消息后就进入阻塞状态,不能继续发送数据,必须等到接收到对方的消息才能继续发送。这个功能实现起来比较简单,在基本通信程序的基础上做一下改动就可以了。而要实现双方可以自由聊天就比较难了,因为需要用新的技术,比如多线程。我是创建了子线程来不断读取数据,主线程里就不断输入数据。当然过程中还是犯了一些常见问题,比如send()函数的第三个参数,应该和实际发送的数据长度匹配,否则可能造成接受方的缓冲区溢出。

第三个项目:数据传输。要求模拟CHAP质询的过程,关键技术是整数的传输。我是这么做的:客户机连接上服务器后,服务器发送数据时,先随机生成一个8 bit整数N放入数组的第一个位置表示将要发送的整数个数;然后随机生成整数1、2作为标识,如1表示生成2字节整数,2表示生成4字节整数,这个标识存入数组的第二个位置;然后往后填充数据,如果第二个位置是1,就随机生成2个8 bit整数往后填充,如果第二个位置是2,就随机生成4个8 bit整数往后填充。然后继续生成标识位,重复上面的过程,直到数据填充完毕。后来看,这么做其实有些复杂了。比较好的做法应该是设计数据帧结构,结合网络字节序实现数据传输的功能。

第四个项目,文件传输。(从这个项目开始尝试MFC)我觉得这是一个相对比较难的项目。在实现的过程中我主要用了2种方法:设置异步套接字模式、多线程。设置异步套接字模式是为了获取网络事件,主要用来接收文件数据,多线程主要用来发送文件数据。发送数据时,首先发送文件的长度(文件长度用CFile结构类型中的GetLength()函数获取);然后发送文件名;之后发送数据部分,根据文件长度选择是否需要开启线程,如果长度小于1MB就直接传输:申请动态内存,大小正好为文件的长度,如果长度大于1MB就另开启一个线程,用循环来完成文件传输,每次动态申请100MB的内存空间,发送之后回收这部分空间,直至发送完成。接收文件时,通过异步套接字模式来通知网络事件,首先接收文件长度(可以根据文件长度来设置进度条),然后接收文件名并创建文件,之后动态开辟内存空间接收数据,并把数据写入文件中。实时记录已接收的文件长度,并与实际的文件大小做比较来判断文件传输是否完成。对于上课时讲到的send函数“发不动”的问题,这里是采用动态申请内存空间,发送完成后即回收空间,所以不会出现下一次发送数据覆盖上一次数据的情况,只在发送文件长度和文件名后调用了Sleep()函数以避免数据覆盖,可以说解决了这样一个问题,缺点可能就是会需要大量的内存空间,相当于是用空间换取时间了。

第五个项目,即时通信系统。这个项目是前面几个项目的综合,设计一个聊天室,可以群聊、私聊,有登录功能和文件传送功能。这个项目用控制台程序也可以做,只是考虑到应该有用户体验,所以打算用MFC,但是由于对MFC不熟悉,所以做的时候还是遇到了不少问题。这个项目最后没有做完整,一是没有添加登录功能,对于登录功能我是想实现用户可以自己任意添加用户名、设置密码,然后服务器动态地创建用户数据,这样会涉及到后台数据库的操作,当然简单的方法是自己设定好用户名和密码,然后用户登录时只能用那几个账号。二是没有添加文件传输的功能。总的来说,这个项目做得并不完整,没有把以前所学到的整合进去,时间花的也不充足。可能感觉有点复杂就产生了畏难心理,但是还是看到一些同学做得比较好,比如费宣同学,很多地方应该向他们学习。

第六个项目,三层通信协议的设计。这个项目主要是实现停等协议,而且我们只需补全一个文件就可以了,也就是通信协议层,其他层面老师已经写好了。这个项目并不难,我是采用有限状态机去做的。关键地方是定时器的设置和超时事件的处理。接收方的程序比较好写,关键是发送方的程序。在发送事件到达时,首先判断发送缓冲区是不是为空,如果不空,说明还没发送完,应该拒绝高层发送,可以用return -1去实现;如果缓冲区为空,就可以往里填数据了。这里数据我采用了结构体的格式,便于实现双方的交互。发送数据时需要判断当前所处的状态,然后根据状态设定数据帧中的一些参数,比如序号。每发送成功一帧就应该启动定时器,在定时时间内如果收到了ACK,就应立即关闭定时器(可以通过一个整形变量来标志定时器的启闭);如果超时,就转到超时事件的处理了,我一开始在处理超时事件时遇到的问题就是没有判断状态,而去在发送模块中处理超时事件,结果就是协议失败。应该在处理超时事件时也要判断状态,然后转到相应的状态处理函数下重传数据,需要注意的是即使是数据的重传也要设置定时器,因为重传也可能还会失败。

当然,这里和项目四的做法不同的是,接收和发送都只有一个缓冲区,对于高层发送太快的问题是采用有限状态机+超时重传机制去解决的。后来用老师给的例程做了停等协议、回退N协议和选择性重传协议的性能比较,统计了一些数据,实实在在地感受到了这几个协议工作的机理,对他们的性能也有了感性的认识,当时学计算机通信网时可真是让人摸不着头脑,而通过实验则一目了然。

最后,感谢段老师为这门课所付出的心血。您勇于试验、勇于课程改革的精神正是现在中国大学的教育所缺少的,虽然这样的改革会让习惯了应试、习惯了仅仅听课的我们很不适应,给您的教学工作也带来了很大的挑战,但是学生相信总会越来越好的。学生也很庆幸参加了您的教改班。

-----EOF-----

Categories: 教育 Tags: 计算机网络