网络编程(课程设计)报告.docx
- 文档编号:743081
- 上传时间:2023-04-30
- 格式:DOCX
- 页数:31
- 大小:241.48KB
网络编程(课程设计)报告.docx
《网络编程(课程设计)报告.docx》由会员分享,可在线阅读,更多相关《网络编程(课程设计)报告.docx(31页珍藏版)》请在冰点文库上搜索。
网络程序设计课程设计报告
班王恩阳孟德龙
2014年12月23日
目录
第1章课设内容与要求 1
1.1课设题目 1
1.2设计目的 1
1.3设计要求 1
第2章设计分析 2
2.1题目分析 2
2.2守护进程原理分析 3
2.3网络套接字原理分析 4
第3章设计实现 5
3.1关键技术设计 5
3.1.1创建守护进程 5
3.1.2I/O复用的select函数 7
3.1.3网络套接字函数 8
3.2关键程序实现 8
3.2.1创建守护进程 8
3.2.2套接字编程 9
3.2.3I/O复用的select函数 10
3.2.4处理客户连接 10
第4章运行与测试 11
4.1测试目的及测试内容 11
4.2设计的测试数据及测试结果 12
第5章总结与心得 16
参考文献 17
附录:
部分源程序 18
第1章课设内容与要求
第1章课设内容与要求
1.1课设题目
设计并实现一个并发、IO复用的守护进程时间服务器,要求学生开发界面,有服务界面和客户端界面,(界面开发语言自己选择,例如
VC,JAVA,GTK/GTKMM,QT其中一个即可)。
1.2设计目的
1)熟练掌握所学到的网络套接字函数。
2)掌握UDP和TCP编程关键函数。
3)掌握多进程或多线程编程。
4)掌握使用select实现I/O复用。
5)掌握守护进程的编写。
6)掌握网络编程的界面开发。
1.3设计要求
1)服务端界面启动,在界面里有表示服务当前的状态,状态分为:
启动、链接、关闭。
2)服务器界面显示客户端链接信息。
3)客户端界面有服务IP地址,服务链接端口,链接服务器信息。
4)客户端具有链接、关闭和重新链接功能。
5)客户端具有发送消息功能,向服务器发送“whatisthetime?
”信息
时,服务器回应当时的系统时间字符串。
显示到客户端界面里,同时服务端界面显示客户端链接IP信息。
第2章设计分析
第2章设计分析
2.1题目分析
我们选择实验的题目1即实现一个并发、IO复用的守护进程时间服务器,要求当客户端向服务器发送“whatisthetime?
”字符串时,服务器回应当时的系统时间字符串。
现在要用守护进程实现一个时间服务器,呈现的功能是:
服务器运行后自动成为守护进程,返回shell;客户端运行后收到服务器发来的当前时间。
从而达到利用网络把时间资讯传递给用户的目的。
要使服务器可以同时处理多个客户端的请求需要用到并发服务器,我们采用I/O多路复用。
详细过程如图2-1服务器端工作流程图所示。
图2-1服务端工作流程图
1
2.2守护进程原理分析
操作系统中在系统引导的时候会开启很多服务,这些服务就叫做守护进程。
为了增加灵活性,root可以选择系统开启的模式,这些模式叫做运行级别,每一种运行级别以一定的方式配置系统。
守护进程是脱离于终端并且在后台运行的进程。
守护进程脱离于终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的终端信息所打断。
在Client/Server模式下,服务器监听(Listen)在一个特定的端口上等待客户连接。
连接成功后服务器和客户端通过端口进行数据通信。
守护进程的工作就是打开一个端口,并且等待(Listen)进入连接。
如果客户端产生一个连接请求,守护进程就创建(Fork)一个子服务器响应这个连接,而主服务器继续监听其他的服务请求。
独立运行的守护进程由init脚本负责管理,所有独立运行的守护进程的脚本在/etc/rc.d/init.d/目录下。
系统服务都是独立运行的守护进程包括:
syslogd和cron等。
运行独立的守护进程工作方式称作:
stand-alone。
传统的C/S模式的访问模式。
服务器监听(Listen)在一个特点的端口上等待客户端的联机。
如果客户端产生一个连接请求,守护进程就创建(Fork)一个子服务器响应这个连接,而主服务器继续监听。
以保持多个子服务器池等待下一个客户端请求。
工作在stand-alone模式下的网络服务有route、gated。
另外是大家最熟悉是Web服务器:
Apache和邮件服务器Sendmail、域名服务器
Bind。
因为这些负载很大服务器上,预先创子服务器,可以通过客户的服务速度。
在Linux系统中可通过stand-alone工作模式启动的服务由/etc/rc.d/下面对应的运行级别当中的符号链接启动。
图2-2守护进程工作模式示意图
第2章设计分析
2.3网络套接字原理分析
要通过互联网进行通信,你至少需要一对套接字,其中一个运行于客户机端,我们称之为ClientSocket,另一个运行于服务器端,我们称之为
ServerSocket。
根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:
服务器监听,客户端请求,连接确认。
所谓服务器监听,是服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。
所谓客户端请求,是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。
为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
所谓连接确认,是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。
而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
在面向连接的客户机/服务器程序工作模式中,服务器进程首先用socket()建立流套接字,在用bind()套接字与本地地址绑定,在用listen()侦听,即准备好接受连接,在用accept()接收连接,然后等待客户进程连接请求的到来,在
用recv()接收数据,send()发送数据,最后用close()关闭套接字;客户端进程,首先用socket()建立套接字,在用connect()将套接字与远程主机连接,在用send()发送数据,recv()接收数据,最后用close()关闭套接字。
3
第3章设计实现
3.1关键技术设计
3.1.1创建守护进程
在linux操作系统中在系统的引导的时候会开启很多服务,这些服务就叫做守护进程。
守护进程是脱离于终端并且在后台运行的进程。
守护进程脱离于终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的终端信息所打断。
守护进程,也就是通常说的Daemon进程,是Linux中的后台服务进程。
它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。
创建一个守护进程如下图3-1守护进程:
图3-1守护进程服务器流程图
第3章设计实现
守护进程常常在系统引导装入时启动,在系统关闭时终止。
由于在Linux中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个终端就称为这些进程的控制终端,当控制终端被关闭时,相应的进程都会自动关闭。
如果想让某个进程不因为用户或终端或其他地变化而受到影响,那么就必须把这个进程变成一个守护进程。
创建守护进程,要先创建子进程,然后再退出父进程。
使用的是系统函数setsid在子进程中创建新会话,从而使进程完全独立出来,从而摆脱其他进程的控制。
改变当前目录为根目录,利用chdir(“/”)更改。
重设文件权限掩码,使新文件的权限位不受原文件模式创建掩码的权限位的影响,使用函数umask()。
close()关闭文件描述符。
同文件权限码一样,用fork函数新建的子进程会从父进程那里继承一些已经打开了的文件。
这些被打开的文件可能永远不会被守护进程读写,但它们一样消耗系统资源,而且可能导致所在的文件系统无法卸下,所以应该被关闭。
5
3.1.2I/O复用的select函数
我们需要服务器具有这样的能力:
如果一个或多个I/O条件满足(如输入已准备好被读,或描述字可以承接更多的输出)时,就被通知到。
这个能力被称为I/O复用,详细过程如图3-2I/O复用的过程。
图3-2I/O复用的过程
如果一个TCP服务器既要处理监听套接口,又要处理已连接套接口,一般要用到I/O复用。
当server要对外提供大量的client请求服务时,假如使用阻塞方式,在单线程中,由于accept和recev都是阻塞式的,那么当一个
client被服务器accept后,它可能在send发送消息时阻塞,因此服务器就会阻塞在recev调用。
即时此时有其他的client进行connect,也无法进行响应。
只有当由socket创建的文件描述符的状态发生改变时,才执行accept操作,并把得到的client的文件描述符进行注册,再次进入select调用。
当select检查到有文件描述符的状态改变时,如果是server的socket创建的文件描述符,则执行accept操作,否则执行recev操作。
当请求的client数目比较多时,select明显能够提高并发性。
3.1.3网络套接字函数
第3章设计实现
面向连接的客户机/服务器程序工作模式,服务器进程首先用socket()建立流套接字,在用bind()套接字与本地地址绑定,在用listen()侦听,即准备好接受连接,在用accept()接收连接,然后等待客户进程连接请求的到来,在用recv()接收数据,send()发送数据,最后用close()关闭套接字;客户端进程,首先用socket()建立套接字,在用connect()将套接字与远程主机连接,在用send()发送数据,recv()接收数据,最后用close()关闭套接字。
如下图3-3面向连接的客户/服务器程序工作模式描绘了网络套接字编程的过程。
3.2关键程序实现
图3-3网络套接字编程的过程
3.2.1创建守护进程
第一次调用fork的目的是保证调用setsid的调用进程不是进程组长。
(而setsid函数是实现与控制终端脱离的唯一方法)。
setsid函数使进程成为新会话的会话头和进程组长,并与控制终端断开连接。
7
第二次调用fork的目的是:
即使守护进程将来打开一个终端设备,也不会自动获得控制终端。
这样可以保证这次生成的进程不再是一个会话头。
忽略SIGHUP信号的原因是,当第一次生成的子进程(会话头)终止时,该会话中的所有进程(第二次生成的子进程)都会收到该信号。
3.2.2套接字编程
bind()函数就是绑定函数,其作用是调用socket()函数产生的套接字分配一个本地协议地址,建立地址与套接字的对应关系。
进程如果绑定了一个特定的本地IP地址到它的套接字上,对于TCP客户端,这就是此套接字上发送的
IP数据包分配了源IP地址;对于TCP服务器端,这就限制了该套接字只接受目的地址为IP的客户连接。
socket()创建TCP套接字,作为TCP通信的传输端点,函数中的family参数指明协议族,type参数指明产生套接字的类型,protocol参数是协议标志,一般在调用socket()函数时将其置为0。
listen()函数,在调用之后服务器的状态从CLOSED转换到了LISTEN状态。
参数sokfd是要设置的描述符;backlog参数规定了请求队列中的最大连接数,对队列中等待服务请求的数目进行了限制。
如果一个服务请求到来时,输入队列已满,该套接字将拒绝连接请求。
accept()函数使服务器接受客户端的连接请求,它将完成队列中的对头条目返回给进程,并产生一个新的套接字描述符,这个新生成的描述符称为“已连接套接字”当已完成对列为空时,进程睡眠,直到有已完成的连接到达时。
TCP客户端使用connect()函数来配置套接字,建立一个与TCP服务器的连接,Connect()函数用于激发TCP的三次握手过程,建立与远程服务的连接,对于TCP连接的状态,conect()导致客户端从CLOSED状态转到了SYN_SENT状态。
若建立成功,也就是connect()调用成功,状态会再变到ESTABLISHED状态;若函数connect()调用失败,则套接字不能再使用,必须关闭。
如果想重新调用socket()函数,生成新的套接字。
bzero()中server要置零的数据的起始地址。
从&servaddr指针所指的地址位置开始,将sizeof(sevaddr)字节置为0,bzero无返回值,并且使用
string.h头文件sizeof的结果等于对象或者类型所占的内存字节数。
第3章设计实现
sockaddr_in为IPv4套接字地址结构通常也称为“网际套接字地址结构”,名字为sockaddr_in。
htons将一个无符号短整型(16位)的主机数值转换为网络字节顺序。
SOCK_STREAM提供面向连接的稳定数据传输,即TCP协议。
OCK_STREAM应用在C语言socket编程中,在进行网络连接前,需要用socket函数向系统申请一个通信端口。
3.2.3I/O复用的select函数
select()它允许进程指示内核等多个事件中的任意一个发生,并仅在一个或多个事件发生或经过指定时间时唤醒进程。
listenfd参数是由socket()函数产生的套接字描述符,在调用accept()
函数前,已经调用listen()函数将此套接字变成了监听套接字。
cliaddr和len用来返回对方的套接字地址结构和对应的结构长度。
3.2.4处理客户连接
connfd是套接字描述符,对于服务器是accept()函数返回的已连接套接字描述符,对客户端是调用socket()函数返回的套接字描述符。
buff是指向发送信息的数据缓冲区。
strlen(buff)指明传送数据的长度。
write()发送成功后返回发送的字节数,失败返回-1。
9
第4章运行与测试
4.1测试目的及测试内容
测试是系统工程中的一个重要问题,它是使用为发现错误所选择的输入和状态的组合而执行代码的过程。
测试可以确保一个项目产品的质量,可以发现系统在执行程序过程中所发生的错误,找到错误位置,这样才能为完善系统提供先决条件。
测试大致目的如下:
1)测试是为了发现错误而执行程序的过程。
2)测试是为了证明程序有错,而不是证明程序无错误。
3)一个好的测试用例是在于它能发现至今未发现的错误。
4)一个成功的测试是发现了至今未发现的错误的测试。
常用的测试技术包括:
静态测试和动态测试。
静态测试是指不用执行程序的测试。
动态测试是通过执行程序,找出系统灿在问题的测试过程。
在此,对测试氛围黑盒测试和白盒测试。
黑盒测试又被称为“功能测试”,它关注的是程序的外部结构,并不考虑内部逻辑结构。
白盒测试是按照程序内部的结构测试程序,检验程序中的每条过程是否都能按预定要求正确工作,而忽略掉它的功能不计。
根据课程设计要求及所完成的项目内容,对该系统程序的测试内容如下:
1)使用白盒测试方法对程序内部结构进行单元测试,发现程序存在的错误。
2)通过黑盒测试方法,验证程序服务器端与客户端连接功能。
3)测试连接过程中能否正确获得IP地址。
4)验证服务器端向客户端发送信息功能是否正常。
5)验证客户端向服务器端发送信息功能是否正常。
6)验证返回系统时间功能是否正常。
第4章运行与测试
4.2设计的测试数据及测试结果
服务器端开始监听并成功连接客户端,同时获取本机IP地址,运行结果如下图4-1所示。
图4-1
客户端与服务器端连接成功,接下来便可以进行消息互相推送的测试。
连接成功界面如下图4-2所示。
图4-2
11
服务器端向客户端成功发送信息,表示服务端向客户端的信息推送功能正常。
界面效果如图4-3所示。
图4-3
客户端接收信息成功,界面如下图4-4所示。
图4-4
第4章运行与测试
客户端向服务器端成功发送信息,表示客户端向服务器端的信息推送功能正常。
界面效果如图4-5所示。
图4-5
服务器端接收信息成功,界面效果如图4-6所示。
图4-6
13
输入“whatisthetime”,成功返回系统时间。
返回系统时间功能正常。
界面如图4-7。
图4-7
第5章总结与心得
第5章总结与心得
在本次网络程序设计课程设计中,我们小组选中的题目是“服务器端客户端通信”,即用守护进程创建一个时间服务器,实现客户端与服务器端的连接,实现一个并发、IO复用的守护进程时间服务器,并且要求开发服务器端与客户端的界面。
当然,这个题目最重要的地方并不在于服务器端与客户端实现了通信,最重要的是以守护进程的方式来实现并且要运用I/O复用。
守护进程,能够突破传统的进程创建与退出方式,不再是随着控制终端的打开和关闭而创建和退出,而是自己成为一个独立的部分,随着整个系统实行运转,不因用户或终端而受到影响,这是以守护进程创建的服务器的最大的优点,而I/O复用要解决TCP服务器既要处理监听端口又要处理以监听端口的问题。
在刚开始确定了这个题目的时候,我们先调试了书上的代码,发现书上给出的程序宏观上符合本次课程设计的概况要求,我们把代码分成若干块,以书中的程序为基础删除和添加功能,在服务器端的程序中,在定义完一系列的头文件后,先用一个函数创建守护进程,其次,编写带有select()函数的I/O复用的并发TCP服务器实现接收客户端消息;在客户端程序中,首先,实现输入字符串并且比较该字符串是否同定义的“whatisthetime”相同,其次,实现同数据端的连接收发数据。
这样,整个代码看起来功能层次分明,也便于学习。
在程序设计与框架学习的过程中,课程设计无疑给了我一个很好的实践机会。
在此总结出了几点技术经验:
1)在解决框架问题时,一定要建立一个周密的模型,然后再进行分析与设计,让问题模块化,这样更有利于问题的解决。
2)通过图形有利于对数据模型的理解。
3)任何程序都需要设计异常功能处理,我在刚做的时候忽略了此功能,这样写出来的程序往往是有缺陷的。
因此,要完成一项任务,我们要从自己的实际出发,既不能局限于书本上的知识,我们一定要站在自身的角度上,刻苦学习,悉心钻研,这样才能圆满的完成任务。
15
参考文献
[1]谢希仁著.计算机网络[M].北京:
电子工业出版社,2003.
[2]张炯著.UNIX网络编程:
使用技术与实例分析[M].北京:
清华大学出版社,
2002.
[3]罗莉琴詹祖桥等著.Windows网络编程[M].北京:
人民邮电出版社,2007.
[4]叶树华著.网络编程实用教程[M].北京:
人民邮电出版社,2007.
附录:
部分源程序
附录:
部分源程序
服务器端:
#include"stdafx.h"#include"TCPServer.h"#include"TCPServerDlg.h"#ifdef_DEBUG
#definenewDEBUG_NEW#undefTHIS_FILE
staticcharTHIS_FILE[]=FILE;#endif
/////////////////////////////////////////////////////////////////////////////classCAboutDlg:
publicCDialog
{
public:
CAboutDlg();
enum{IDD=IDD_ABOUTBOX};
protected:
virtualvoidDoDataExchange(CDataExchange*pDX);protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg:
:
CAboutDlg():
CDialog(CAboutDlg:
:
IDD)
{
{{AFX_DATA_INIT(CAboutDlg)
}}AFX_DATA_INIT
}
voidCAboutDlg:
:
DoDataExchange(CDataExchange*pDX)
{
CDialog:
:
DoDataExchange(pDX);
{{AFX_DATA_MAP(CAboutDlg)
}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg,CDialog)
{{AFX_MSG_MAP(CAboutDlg)Nomessagehandlers
}}AFX_MSG_MAP
END_MESSAGE_MAP()
17
/////////////////////////////////////////////////////////////////////////////CTCPServerDlg:
:
CTCPServerDlg(CWnd*pParent/*=NULL*/)
:
CDialog(CTCPServerDlg:
:
IDD,pParent)
{
m_szRecv=_T("");
m_szSend=_T("");m_szServerIP=_T("");
m_hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
voidCTCPServerDlg:
:
DoDataExchange(CDataExchange*pDX)
{
CDialog:
:
DoDataExchange(pDX);DDX_Text(pDX,IDC_EDIT1,m_szRecv);DDX_Text(pDX,IDC_EDIT2,m_szSend);DDX_Text(pDX,IDC_EDIT3,m_szServerIP);
}
BEGIN_MESSAGE_MAP(CTCPServerDlg,CDialog)ON_WM_SYSCOMMAND()
ON_WM_PAIN
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 网络 编程 课程设计 报告