收藏 分享(赏)

网络编程课程设计报告.doc

上传人:dzzj200808 文档编号:2727494 上传时间:2018-09-26 格式:DOC 页数:30 大小:641.45KB
下载 相关 举报
网络编程课程设计报告.doc_第1页
第1页 / 共30页
网络编程课程设计报告.doc_第2页
第2页 / 共30页
网络编程课程设计报告.doc_第3页
第3页 / 共30页
网络编程课程设计报告.doc_第4页
第4页 / 共30页
网络编程课程设计报告.doc_第5页
第5页 / 共30页
点击查看更多>>
资源描述

1、网络程序设计课程设计报告123301 班20124738 王恩阳20124696 孟德龙2014 年 12 月 23 日目录第 1章 课设内容与要求 11.1课设题目 .11.2设计目的 .11.3设计要求 .1第 2章 设计分析 22.1题目分析 .22.2守护进程原理分析 .32.3网络套接字原理分析 .4第 3章 设计实现 53.1关键技术设计 .53.1.1创建守护进程 .53.1.2 I/O复用的 select函数 .73.1.3网络套接字函数 .83.2关键程序实现 .83.2.1创建守护进程 .83.2.2套接字编程 .93.2.3 I/O复用的 select函数 .103.2.

2、4 处理客户连接 10第 4章 运行与测试 114.1测试目的及测试内容 .114.2设计的测试数据及测试结果 .12第 5章 总结与心得 16参考文献 17附录:部分源程序 18第 1 章课设内容与要求第 1章 课设内容与要求1.1课设题目设计并实现一个并发、IO 复用的守护进程时间服务器,要求学生开发界面,有服务界面和客户端界面,(界面开发语言自己选择,例如VC,JAVA,GTKGTKMM,QT 其中一个即可)。1.2设计目的1)熟练掌握所学到的网络套接字函数。2)掌握 UDP和 TCP编程关键函数。3)掌握多进程或多线程编程。4)掌握使用 select实现 I/O复用。5)掌握守护进程的

3、编写。6)掌握网络编程的界面开发。1.3设计要求1)服务端界面启动,在界面里有表示服务当前的状态,状态分为:启动、链接、关闭。2)服务器界面显示客户端链接信息。3)客户端界面有服务 IP地址,服务链接端口,链接服务器信息。4)客户端具有链接、关闭和重新链接功能。5)客户端具有发送消息功能,向服务器发送“what is the time?”信息时,服务器回应当时的系统时间字符串。显示到客户端界面里,同时服务端界面显示客户端链接 IP信息。第 2 章设计分析1第 2章 设计分析2.1题目分析我们选择实验的题目 1即实现一个并发、IO 复用的守护进程时间服务器,要求当客户端向服务器发送“what i

4、s the time?”字符串时,服务器回应当时的系统时间字符串。 现在要用守护进程实现一个时间服务器,呈现的功能是:服务器运行后自动成为守护进程,返回 shell;客户端运行后收到服务器发来的当前时间。从而达到利用网络把时间资讯传递给用户的目的。 要使服务器可以同时处理多个客户端的请求需要用到并发服务器,我们采用 I/O多路复用。详细过程如图 2-1服务器端工作流程图所示。图 2-1服务端工作流程图第 2 章设计分析22.2守护进程原理分析 操作系统中在系统引导的时候会开启很多服务,这些服务就叫做守护进程。为了增加灵活性,root 可以选择系统开启的模式,这些模式叫做运行级别,每一种运行级别

5、以一定的方式配置系统。 守护进程是脱离于终端并且在后台运行的进程。守护进程脱离于终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的终端信息所打断。在 Client/Server模式下,服务器监听(Listen)在一个特定的端口上等待客户连接。连接成功后服务器和客户端通过端口进行数据通信。守护进程的工作就是打开一个端口,并且等待(Listen)进入连接。如果客户端产生一个连接请求,守护进程就创建(Fork)一个子服务器响应这个连接,而主服务器继续监听其他的服务请求。独立运行的守护进程由 init脚本负责管理,所有独立运行的守护进程的脚本在/etc/rc.d/in

6、it.d/目录下。系统服务都是独立运行的守护进程包括:syslogd和 cron等。运行独立的守护进程工作方式称作:standalone。传统的 C/S模式的访问模式。服务器监听(Listen)在一个特点的端口上等待客户端的联机。如果客户端产生一个连接请求,守护进程就创建(Fork)一个子服务器响应这个连接,而主服务器继续监听。以保持多个子服务器池等待下一个客户端请求。工作在 standalone 模式下的网络服务有 route、gated。另外是大家最熟悉是 Web服务器:Apache 和邮件服务器 Sendmail、域名服务器Bind。因为这些负载很大服务器上,预先创子服务器,可以通过客户

7、的服务速度。在 Linux系统中可通过 standalone 工作模式启动的服务由/etc/rc.d/下面对应的运行级别当中的符号链接启动。图 2-2 守护进程工作模式示意图第 2 章设计分析32.3网络套接字原理分析要通过互联网进行通信,你至少需要一对套接字,其中一个运行于客户机端,我们称之为 ClientSocket,另一个运行于服务器端,我们称之为ServerSocket。 根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认。所谓服务器监听,是服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状

8、态。 所谓客户端请求,是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。所谓连接确认,是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。在面向连接的客户机/服务器程序工作模式中,服务器进程首先用 socket()建立流套接字,在用 bind()套接字与本

9、地地址绑定,在用 listen()侦听,即准备好接受连接,在用 accept()接收连接,然后等待客户进程连接请求的到来,在用 recv()接收数据,send()发送数据,最后用 close()关闭套接字;客户端进程,首先用 socket()建立套接字,在用 connect()将套接字与远程主机连接,在用 send()发送数据,recv()接收数据,最后用 close()关闭套接字。第 3 章设计实现4第 3章设计实现3.1关键技术设计3.1.1创建守护进程在 linux操作系统中在系统的引导的时候会开启很多服务,这些服务就叫做守护进程。守护进程是脱离于终端并且在后台运行的进程。守护进程脱离于

10、终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的终端信息所打断。 守护进程,也就是通常说的 Daemon进程,是 Linux中的后台服务进程。它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。创建一个守护进程如下图 3-1守护进程:图 3-1守护进程服务器流程图第 3 章设计实现5守护进程常常在系统引导装入时启动,在系统关闭时终止。由于在 Linux中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个终端就称为这些进程的控制终端,当控制终端被关闭时,相应的进程都会自动关闭

11、。如果想让某个进程不因为用户或终端或其他地变化而受到影响,那么就必须把这个进程变成一个守护进程。创建守护进程,要先创建子进程,然后再退出父进程。 使用的是系统函数 setsid在子进程中创建新会话,从而使进程完全独立出 来,从而摆脱其他进程的控制。改变当前目录为根目录,利用 chdir(“/”)更改。重设文件权限掩码,使新文件的权限位不受原文件模式创建掩码的权限位 的影响,使用函数 umask()。close()关闭文件描述符。同文件权限码一样,用 fork函数新建的子进程会 从父进程那里继承一些已经打开了的文件。这些被打开的文件可能永远 不会被守护进程读写,但它们一样消耗系统资源,而且可能导

12、致所在的文件系统无法卸下,所以应该被关闭。 第 3 章设计实现63.1.2 I/O复用的 select函数 我们需要服务器具有这样的能力:如果一个或多个 I/O条件满足(如输入已准备好被读,或描述字可以承接更多的输出)时,就被通知到。这个能力被称为 I/O复用,详细过程如图 3-2 I/O复用的过程。图 3-2 I/O复用的过程如果一个 TCP服务器既要处理监听套接口,又要处理已连接套接口,一般要用到 I/O复用。当 server要对外提供大量的 client请求服务时,假如使用阻塞方式,在单线程中,由于 accept和 recev都是阻塞式的,那么当一个client被服务器 accept后,

13、它可能在 send发送消息时阻塞,因此服务器就会阻塞在 recev调用。即时此时有其他的 client进行 connect,也无法进行响应。只有当由 socket创建的文件描述符的状态发生改变时,才执行 accept操作,并把得到的 client的文件描述符进行注册,再次进入 select调用。当 select检查到有文件描述符的状态改变时,如果是 server的 socket创建的文件描述符,则执行 accept操作,否则执行 recev操作。当请求的 client数目比较多时, select 明显能够提高并发性。 第 3 章设计实现73.1.3网络套接字函数 面向连接的客户机/服务器程序工

14、作模式,服务器进程首先用 socket()建立流套接字,在用 bind()套接字与本地地址绑定,在用 listen()侦听,即准备好接受连接,在用 accept()接收连接,然后等待客户进程连接请求的到来,在用 recv()接收数据,send()发送数据,最后用 close()关闭套接字;客户端进程,首先用 socket()建立套接字,在用 connect()将套接字与远程主机连接,在用 send()发送数据,recv()接收数据,最后用 close()关闭套接字。如下图3-3 面向连接的客户/服务器程序工作模式描绘了网络套接字编程的过程。图 3-3网络套接字编程的过程3.2关键程序实现 3.

15、2.1创建守护进程第一次调用 fork的目的是保证调用 setsid的调用进程不是进程组长。(而 setsid 函数是实现与控制终端脱离的唯一方法)。 setsid函数使进程成为新会话的会话头和进程组长,并与控制终端断开连 第 3 章设计实现8接。 第二次调用 fork的目的是:即使守护进程将来打开一个终端设备,也不会 自动获得控制终端。这样可以保证这次生成的进程不再是一个会话头。 忽略 SIGHUP信号的原因是,当第一次生成的子进程(会话头)终止时, 该会话中的所有进程(第二次生成的子进程)都会收到该信号。3.2.2套接字编程bind()函数就是绑定函数,其作用是调用 socket()函数产

16、生的套接字分配一 个本地协议地址,建立地址与套接字的对应关系。进程如果绑定了一个特定的本地 IP地址到它的套接字上,对于 TCP客户端,这就是此套接字上发送的IP数据包分配了源 IP地址;对于 TCP服务器端,这就限制了该套接字只接受目的地址为 IP的客户连接。 socket()创建 TCP套接字,作为 TCP通信的传输端点,函数中的 family参 数指明协议族,type 参数指明产生套接字的类型,protocol 参数是协议标志,一般在调用 socket()函数时将其置为 0。 listen()函数,在调用之后服务器的状态从 CLOSED转换到了 LISTEN状态。参数 sokfd是要设置

17、的描述符;backlog 参数规定了请求队列中的最大连接数,对队列中等待服务请求的数目进行了限制。如果一个服务请求到来时,输入队列已满,该套接字将拒绝连接请求。 accept()函数使服务器接受客户端的连接请求,它将完成队列中的对头条目 返回给进程,并产生一个新的套接字描述符,这个新生成的描述符称为“已连接套接字”当已完成对列为空时,进程睡眠,直到有已完成的连接到达时。 TCP客户端使用 connect()函数来配置套接字,建立一个与 TCP服务器的连 接,Connect()函数用于激发 TCP的三次握手过程,建立与远程服务的连接,对于 TCP连接的状态,conect()导致客户端从 CLOS

18、ED状态转到了 SYN_SENT状态。若建立成功,也就是 connect()调用成功,状态会再变到 ESTABLISHED状态;若函数 connect()调用失败,则套接字不能再使用,必须关闭。如果想重新调用 socket()函数,生成新的套接字。 bzero()中 server 要置零的数据的起始地址。从#endif/class CAboutDlg : public CDialogpublic:CAboutDlg();enum IDD = IDD_ABOUTBOX ;protected:virtual void DoDataExchange(CDataExchange* pDX); prot

19、ected:DECLARE_MESSAGE_MAP();CAboutDlg:CAboutDlg() : CDialog(CAboutDlg:IDD)AFX_DATA_INIT(CAboutDlg)AFX_DATA_INITvoid CAboutDlg:DoDataExchange(CDataExchange* pDX)CDialog:DoDataExchange(pDX);AFX_DATA_MAP(CAboutDlg)AFX_DATA_MAPBEGIN_MESSAGE_MAP(CAboutDlg, CDialog)AFX_MSG_MAP(CAboutDlg)No message handler

20、sAFX_MSG_MAPEND_MESSAGE_MAP()附录:部分源程序18/CTCPServerDlg:CTCPServerDlg(CWnd* pParent /*=NULL*/): CDialog(CTCPServerDlg:IDD, pParent)m_szRecv = _T(“);m_szSend = _T(“);m_szServerIP = _T(“);m_hIcon = AfxGetApp()-LoadIcon(IDR_MAINFRAME);void CTCPServerDlg:DoDataExchange(CDataExchange* pDX)CDialog:DoDataExc

21、hange(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_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_BUTTON1, OnAcceptBtn)ON_BN_CLICKED(IDC_BUTTON2, OnSend)ON_BN_CLICKED(

22、IDC_BUTTON4, OnButton4)ON_BN_CLICKED(IDC_BUTTON3, OnCancel)ON_EN_CHANGE(IDC_EDIT2, OnChangeEdit2)END_MESSAGE_MAP()/BOOL CTCPServerDlg:OnInitDialog()CDialog:OnInitDialog();ASSERT(IDM_ABOUTBOX ASSERT(IDM_ABOUTBOX AppendMenu(MF_SEPARATOR);pSysMenu-AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);SetIc

23、on(m_hIcon, TRUE); / Set big iconSetIcon(m_hIcon, FALSE); / Set small iconm_sockListen.SetParent(this);m_sockServer.SetParent(this);m_sockListen.Create(10000);return TRUE; / return TRUE unless you set the focus to a controlvoid CTCPServerDlg:OnSysCommand(UINT nID, LPARAM lParam)if (nID dlgAbout.DoMo

24、dal();elseCDialog:OnSysCommand(nID, lParam);void CTCPServerDlg:OnPaint() if (IsIconic()CPaintDC dc(this); SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);int cxIcon = GetSystemMetrics(SM_CXICON);附录:部分源程序20int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(int x = (rect.Wid

25、th() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;dc.DrawIcon(x, y, m_hIcon);elseCDialog:OnPaint();HCURSOR CTCPServerDlg:OnQueryDragIcon()return (HCURSOR) m_hIcon;void CTCPServerDlg:OnReceive()BYTE byBuf1024 = 0;/接受缓冲区int nRecvLen = 0;nRecvLen = m_sockServer.Receive(byBuf,sizeof(byBuf)

26、;CString tmp;if(nRecvLen 0)UpdateData();tmp.Format(“%srn“,byBuf);/格式化变量m_szRecv+=tmp;UpdateData(FALSE);/显示tmp = “what is the time“ ? byBuf1023 = 1 : byBuf1023 = 0;elseAfxMessageBox(“收到的数据有问题!“);void CTCPServerDlg:OnAccept()附录:部分源程序21CString Dizhi;char szHostName128 = 0;gethostname(szHostName, 128);h

27、ostent* phostent = gethostbyname(szHostName);char* szIP = inet_ntoa(*(in_addr*)Dizhi = szIP;SOCKADDR sockAddr;/保存地址变量int nSockAddrLen = sizeof(SOCKADDR);CString tmp;/临时字符串变量if(m_sockListen.Accept(m_sockServer,m_szRecv+=tmp;m_szRecv+=Dizhi;m_szRecv+=“rn“;UpdateData(FALSE);void CTCPServerDlg:OnClose()

28、void CTCPServerDlg:OnAcceptBtn() m_sockListen.Listen();void CTCPServerDlg:OnSend() UpdateData();/更新数据到变量int nSendLen = m_sockServer.Send(void*)m_szSend.GetBuffer(0),m_szSend.GetLength();/发送字符串if(nSendLen 0)AfxMessageBox(“发送成功!“);附录:部分源程序22elseAfxMessageBox(“发送失败!“);void CTCPServerDlg:OnCancel() CDia

29、log:OnCancel();void CTCPServerDlg:OnButton4() char szHostName128 = 0;gethostname(szHostName, 128);hostent* phostent = gethostbyname(szHostName);char* szIP = inet_ntoa(*(in_addr*)m_szServerIP = szIP;UpdateData(FALSE);客户端:#include “stdafx.h“#include “TCPClient.h“#include “TCPClientDlg.h“#ifdef _DEBUG#

30、define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE = _FILE_;#endif/class CAboutDlg : public CDialogpublic:CAboutDlg();enum IDD = IDD_ABOUTBOX ;附录:部分源程序23protected:virtual void DoDataExchange(CDataExchange* pDX); protected:DECLARE_MESSAGE_MAP();void CAboutDlg:DoDataExchange(CDataExchange* pDX)

31、CDialog:DoDataExchange(pDX);BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)AFX_MSG_MAP(CAboutDlg)AFX_MSG_MAPEND_MESSAGE_MAP()/CTCPClientDlg:CTCPClientDlg(CWnd* pParent /*=NULL*/): CDialog(CTCPClientDlg:IDD, pParent)m_szSend = _T(“);m_szRecv = _T(“);m_hIcon = AfxGetApp()-LoadIcon(IDR_MAINFRAME);void CTCPClient

32、Dlg:DoDataExchange(CDataExchange* pDX)CDialog:DoDataExchange(pDX);DDX_Text(pDX, IDC_EDIT2, m_szSend);DDX_Text(pDX, IDC_EDIT1, m_szRecv);BEGIN_MESSAGE_MAP(CTCPClientDlg, CDialog)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_BUTTON1, OnConnectBtn)ON_BN_CLICKED(IDC_BUTTON2, OnSe

33、nd)ON_BN_CLICKED(IDC_BUTTON3, OnButton3)ON_BN_CLICKED(IDC_BUTTON4, OnButton4)附录:部分源程序24ON_WM_TIMER()ON_EN_CHANGE(IDC_EDIT2, OnChangeEdit2)ON_EN_CHANGE(IDC_EDIT1, OnChangeEdit1)END_MESSAGE_MAP()/BOOL CTCPClientDlg:OnInitDialog()CDialog:OnInitDialog();ASSERT(IDM_ABOUTBOX ASSERT(IDM_ABOUTBOX AppendMenu

34、(MF_SEPARATOR);pSysMenu-AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);SetIcon(m_hIcon, TRUE);SetIcon(m_hIcon, FALSE);m_sockConnect.Create();m_sockConnect.SetParent(this);return TRUE; / return TRUE unless you set the focus to a controlvoid CTCPClientDlg:OnSysCommand(UINT nID, LPARAM lParam)if (nI

35、D dlgAbout.DoModal();else附录:部分源程序25CDialog:OnSysCommand(nID, lParam);void CTCPClientDlg:OnPaint() /画图函数if (IsIconic()CPaintDC dc(this); SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);int cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRe

36、ct(int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;dc.DrawIcon(x, y, m_hIcon);elseCDialog:OnPaint();HCURSOR CTCPClientDlg:OnQueryDragIcon()return (HCURSOR) m_hIcon;void CTCPClientDlg:OnConnect()UpdateData();m_szRecv += CString(“连接成功!rn“);UpdateData(FALSE);void CTCPCl

37、ientDlg:OnReceive()CTime time1;CString str,str1;附录:部分源程序26time1 = CTime:GetCurrentTime();str = time1.Format(“%H:%M:%S“);BYTE byBuf1024 = 0;int nRecvLen = 0;nRecvLen = m_sockConnect.Receive(byBuf,sizeof(byBuf);CString tmp;if(nRecvLen 0)UpdateData();tmp.Format(“%srn“,byBuf);m_szRecv+=tmp;if(byBuf1023

38、= 1)MessageBox(str,NULL,MB_OK);UpdateData(FALSE);elseAfxMessageBox(“收到的数据有问题!“);void CTCPClientDlg:OnConnectBtn() char szHostName128 = 0;gethostname(szHostName, 128);hostent* phostent = gethostbyname(szHostName);char* szIP = inet_ntoa(*(in_addr*)char * lpIP = szIP;m_sockConnect.Connect(lpIP,10000);v

39、oid CTCPClientDlg:OnSend() CTime time1;CString str,str1;time1 = CTime:GetCurrentTime();str = time1.Format(“%H:%M:%S“);UpdateData();int nSendLen = 附录:部分源程序27m_sockConnect.Send(void*)m_szSend.GetBuffer(0),m_szSend.GetLength();if(nSendLen = 16)MessageBox(str,NULL,MB_OK);if(nSendLen 0)AfxMessageBox(“发送成

40、功!“);elseAfxMessageBox(“发送失败!“);void CTCPClientDlg:OnButton3() CDialog:OnCancel();void CTCPClientDlg:OnButton4() CTime time1;CString str,str1;time1 = CTime:GetCurrentTime();str = time1.Format(“%H:%M:%S“);MessageBox(str,NULL,MB_OK);*/void CTCPClientDlg:OnTimer(UINT nIDEvent) CDialog:OnTimer(nIDEvent);

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 高等教育 > 大学课件

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报