计算机网络课设设计报告.docx
《计算机网络课设设计报告.docx》由会员分享,可在线阅读,更多相关《计算机网络课设设计报告.docx(37页珍藏版)》请在冰点文库上搜索。
计算机网络课设设计报告
成绩:
2015-2016学年第2学期
《计算机网络》课程设计
DAY1:
题目:
VS2013/MFC基于对话框编程
学院名称:
班级学号:
学生姓名:
教师姓名:
2016年7月
1.创建MFC工程
(1)双击打开VS2013,进入起始页,在左侧开始处选择“新建项目”;或者选择菜单栏中“文件”,依次选择“新建”、“项目”。
(2)选择新建项目后,在新建项目对话框中选择模块->VisualC++->MFC->MFC应用程序,并确定好存放路径和项目名称,点击“确定”。
(3)进入应用程序向导,一开始会给出默认的项目配置,点击“下一步”即可。
(4)选择“基于对话框”,MFC可以选择在静态库中使用,或者在共享DLL中使用。
一般选择共享使用就行,静态库中使用会把所有用到的dll集成到exe文件中,最终生成的文件一般可以直接使用,但占用更大空间。
(5)选择主框架样式,可以自由选择是否添加最小化框、最大化框。
如果觉得没必要“关于”对话框也可以去掉,对话框标题一般不需要更改。
(6)高级功能一般默认即可,但如果用不上“ActiveX控件”可以去掉勾选;如果需要涉及网络编程就把“windows套接字”选上。
不过没选上也不要紧,在程序中可以自己添加部分代码导入套接字。
(7)最后是自动生成的两个类的头文件和源文件名称,可以修改基类,但一般不用改,默认完成就行。
至此,一个基于对话框的MFC项目就创建好了。
2.MFC执行流程
(1)每创建一个项目,一般会包含3个类,“关于”对话框类、主对话框类以及用于初始化项目的App类,假如项目名称为Demo,那么这三个类分别为CAboutDlg、CDemoDlg、
CDemoApp。
(2)项目生成后,都会生成一个属于CDemoApp类的theApp对象,对本应用程序实例化,这个在CDemoApp.cpp文件中定义,创建时调用构造函数CDemoApp:
:
CDemoApp();这就是程序创建的第一步。
(3)接下来程序会调用winmain函数,这个在项目文件中找不到,但可以在VS2013的安装路径下找到,其函数声明为:
intAFXAPIAfxWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,_In_LPTSTRlpCmdLine,intnCmdShow);
(4)调用完winmain后,就通过InitInstance()函数初始化窗口,包括注册、创建和显示对话框,InitInstance函数是CDemoApp类中除构造函数以外唯一的成员函数。
一般不需要修改这部分程序,但有些时候可以添加部分代码,比如需要创建多个对话框时,刚启动时弹出的对话框(比如用于登录)不是主对话框,就可以在这个函数里创建主对话框之前调用登录对话框,这样就可以设置启动时的默认对话框了。
(5)应用程序创建完了,程序开始运行了,于是进入消息循环,windows程序的事件都是消息驱动的,每产生一个消息就触发一个响应事件,消息和事件通过消息映射DECLARE_MESSAGE_MAP()联系在一起。
默认包含三个消息:
ON_WM_SYSCOMMAND()//响应控制指令
ON_WM_PAINT()//响应绘图消息,用于刷新窗口
ON_WM_QUERYDRAGICON()//当用户拖动最小化窗口时取得光标
(6)当用户关闭应用程序时,会发送一个WM_CLOSE消息,程序响应后结束程序,如何在点击关闭时需要弹出其他对话框(比如用于提示保存),可以通过类向导添加WM_CLOSE消息处理函数,变添加相关处理程序,比如:
voidCDemoDlg:
:
OnClose()
{
if(MessageBox(_T("确定退出吗"),_T("提示"),MB_YESNO|MB_ICONWARNING)==IDNO)
return;
CDialogEx:
:
OnClose();
}
(7)这样,一个应用程序通过定义,初始化,由winmain开始,注册、创建、显示窗口,消息响应,程序终止完成了他的运行周期。
3.对话框类
(1)首先看看对话框类的继承关系,新建的项目类派生于CDialogEx类,CDialogEx在CDialog
类的基础上进行了扩展,而CDialog派生于窗口类CWnd,说明对话框也属于一种窗口。
这
样对于对话框类的继承关系就有了一定了解。
(2)打开项目的头文件,最上面的#pragmaonce表示后面的头文件只编译一次;默认生成的函数有:
CDemoDlg(CWnd*pParent=NULL);//标准构造函数
virtualvoidDoDataExchange(CDataExchange*pDX);//DDX/DDV支持
//生成的消息映射函数
virtualBOOLOnInitDialog();
afx_msgvoidOnSysCommand(UINTnID,LPARAMlParam);
afx_msgvoidOnPaint();
afx_msgHCURSOROnQueryDragIcon();
DECLARE_MESSAGE_MAP()//消息映射的声明
三个消息在前一经验已经介绍过,构造函数自然是创建对话框时自动调用,DoDataExchange
函数用于存放各类控件的变量信息,OnInitDialog用来初始化对话框。
(3)打开源文件可以看到各个函数的定义,“关于”对话框类的成员函数和消息映射也在这里,不多述。
先讲述构造函数CDemoDlg(),通过类向导生成的自定义变量或者控件的关联变量都会在构造函数中初始化一个值,不过开发者也可以直接在头文件定义变量,并手动在构造函数中添加初始化语句。
所以说,构造函数是个赋初值的好地方。
(4)再来看DoDataExchange函数,在对话框中添加新的控件并通过类向导定义了相关变量后,都会在这个用于数据交换的函数中说明,添加变量的最大最小值也会在这里体现。
(5)下面是消息映射,定义了所有消息的来源和处理函数,对于自定义消息或者某些无法通过类向导完成的消息,可以手动在这里添加映射关系,并在别处添加对应的处理函数。
(6)初始化函数OnInitDialog,默认用来设置图标和菜单,很多时候有些操作需要在启动对话框前就做好,比如说某些控件的初始状态(按钮是否可视、是否可操作),这些初始化的设置都可以在OnInitDialog函数中添加,最好在提示语“//TODO:
在此添加额外的初始化代码”的下面添加。
(7)系统指令响应函数OnSysCommand,默认处理窗口最小化和最大化指令等,并会根据是否选中“关于”决定是否弹出“关于”对话框。
这个函数一般不需要修改。
(8)绘图消息响应函数OnPaint用于绘制窗口和图标,其中CRect是个存储窗口大小的结构体。
OnQueryDragIcon函数用于返回光标,这不多讲。
(9)默认生成的函数就这么多,其他常用的消息有定时器消息WM_TIMER、窗口关闭消息WM_CLOSE、应用程序结束消息WM_DESTROY、按钮按下消息WM_KEYDOWN等。
而
常用的虚函数一般有PreTranslateMessage、PreCreateWindow等,这些以后用到再具体说明。
4.按钮的使用
按钮(Button)可以说是对话框中最常用的控件之一,也是人机交互中必不可少的控件之一。
许多事件都是通过按钮按下来触发的。
(1)在工具箱中找到对话框,按钮名称是Button。
把对话框原有的按钮和静态文本删除,从工具箱中添加两个按钮到对话框中。
(2)选中任意一个按钮,在属性页中可以查看按钮的所有属性。
一般需要修改的属性只有两个,“Caption”项和“ID”项,前者表示按钮文本,后者是按钮ID,就像是人的身份证号一样是唯一的。
其余常用属性:
1、Disabled:
使能,为真(true)表示按钮可以按下,为假(false)表示按钮为灰,不能操作
2、Visible:
可见,为真表示按钮可见,为假表示按钮不可见
3、Multiline:
多行,为真表示按钮文本可以多行显示,为假表示按钮文本不可换行显示说明:
对于只有真假两种选项的属性,可以双击属性名称进行切换"true"或"false"。
选中属性名称,在属性页最下方都会有属性说明。
说明:
1、变量名一般以"m_"开头,后面部分为按钮功能的说明,这样方便记忆和识别;
2、按钮只有控件型的变量;
3、如果有必要的话可以添加一定的注释。
5.编辑框
编辑框(EditControl)作为对话框中常用的控件之一,常用来输入文本或者显示文本,比如用户名和密码的输入,当前数据的显示等等都少不了编辑框。
(1)从工具箱中找到编辑框(EditControl),拖动到对话框中。
(2)首先选中任意一个编辑框,看看编辑框都有哪些属性,其中常用到属性有:
Multiline:
多行,表示内容可以多行显示,一般记录性的编辑框需要多行;
Password:
密码,表示文本以密码形式呈现,一般用来输出密码;
Readonly:
只读,表示文本内容只能读不能写;
Number:
数字,表示只能输入数字;
Lowercase:
小写,所有字母全部自动转换为小写显示;
Uppercase:
大写,所有字母全部自动转换为大写显示;
Horizontalscroll:
水平滚动条,需要先选中Multiline属性;
Verticalscroll:
垂直滚动条,需要先选中Multiline属性;
成绩:
2015-2016学年第2学期
《计算机网络》课程设计
DAY2:
题目:
SOCKET编程
学院名称:
班级学号:
学生姓名:
教师姓名:
2016年7月
1.Socket简介
80年代初,美国政府的高级研究工程机构(ARPA)给加利福尼亚大学Berkeley分校提供了资金,让他们在UNIX操作系统下实现TCP/IP协议。
在这个项目中,研究人员为TCP/IP网络通信开发了一个API(应用程序接口)。
这个API称为Socket接口(套接字)。
今天,SOCKET接口是TCP/IP网络最为通用的API,也是在INTERNET上进行应用开发最为通用的API。
90年代初,由Microsoft联合了其他几家公司共同制定了一套WINDOWS下的网络编程接口,即WindowsSockets规范。
它是BerkeleySockets的重要扩充,主要是增加了一些异步函数,并增加了符合Windows消息驱动特性的网络事件异步选择机制。
WINDOWSSOCKETS规范是一套开放的、支持多种协议的Windows下的网络编程接口。
从1991年的1.0版到1995年的2.0.8版,经过不断完善并在Intel、Microsoft、Sun、SGI、Informix、Novell等公司的全力支持下,已成为Windows网络编程的事实上的标准。
目前,在实际应用中的WINDOWSSOKCETS规范主要有1.1版和2.0版。
两者的最重要区别是1.1版只支持TCP/IP协议,而2.0版可以支持多协议。
2.0版有良好的向后兼容性,任何使用1.1版的源代码,二进制文件,应用程序都可以不加修改地在2.0规范下使用。
SOCKET实际在计算机中提供了一个通信端口,可以通过这个端口与任何一个具有SOCKET接口的计算机通信。
应用程序在网络上传输,接收的信息都通过这个SOCKET接口来实现。
在应用开发中就像使用文件句柄一样,可以对SOCKET句柄进行读,写操作。
Socket可以支持数据的发送和接收,它会定义一种称为套接字的变量,发送数据时首先创建套接字,然后使用该套接字的sendto等方法对准某个IP/端口进行数据发送;接收端也首先创建套接字,然后将该套接字绑定到一个IP/端口上,所有发向此端口的数据会被该套接字的recv等函数读出。
如同读出文件中的数据一样。
2.所需的头文件、库文件和DLL
对于目前使用最广泛的WindowsSocket2.0版本,所需的一些文件如下(以安装了VC6为例说明其物理位置):
● 头文件winsock2.h,通常处于C:
"ProgramFiles"MicrosoftVisualStudio"VC98"INCLUDE;查看该头文件可知其中又包含了windows.h和pshpack4.h头文件,因此在windows中的一些常用API都可以使用;
● 库文件Ws2_32.lib,通常处于C:
"ProgramFiles"MicrosoftVisualStudio"VC98"Lib;
● DLL文件Ws2_32.dll,通常处于C:
"WINDOWS"system32
3.部分类型与函数
1)SOCKET类型
SOCKET是socket套接字类型,在WINSOCK2.H中有如下定义:
typedefunsignedintu_int;
typedefu_int SOCKET;
可知套接字实际上就是一个无符号整型,它将被Socket环境管理和使用。
套接字将被创建、设置、用来发送和接收数据,最后会被关闭。
2)WORD类型
WORD类型是一个16位的无符号整型,在WTYPES.H中被定义为:
typedefunsignedshortWORD;
其目的是提供两个字节的存储,在Socket中这两个字节可以表示主版本号和副版本号。
3)WSADATA类型
WSADATA类型是一个结构,描述了Socket库的一些相关信息,其结构定义如下:
typedefstructWSAData{
WORD wVersion;
WORD wHighVersion;
char szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYS_STATUS_LEN+1];
unsignedshort iMaxSockets;
unsignedshort iMaxUdpDg;
charFAR* lpVendorInfo;
}WSADATA;
typedefWSADATAFAR*LPWSADATA;
值得注意的就是wVersion字段,存储了Socket的版本类型。
LPWSADATA是WSADATA的指针类型。
它们不用程序员手动填写,而是通过Socket的初始化函数WSAStartup读取出来。
4)Socket函数
socket的创建函数,其定义为:
SOCKETPASCALFARsocket(intaf,inttype,intprotocol);
第一个参数为intaf,代表网络地址族,目前只有一种取值是有效的,即AF_INET,代表internet地址族;
第二个参数为inttype,代表网络协议类型,SOCK_DGRAM代表UDP协议,SOCK_STREAM代表TCP协议;
第三个参数为intprotocol,指定网络地址族的特殊协议,目前无用,赋值0即可。
返回值为SOCKET,若返回INVALID_SOCKET则失败。
5)sockaddr_in、in_addr类型,inet_addr、inet_ntoa函数
sockaddr_in定义了socket发送和接收数据包的地址,定义:
structsockaddr_in{
short sin_family;
u_shortsin_port;
struct in_addrsin_addr;
char sin_zero[8];
};
其中in_addr的定义如下:
structin_addr{
union{
struct{u_chars_b1,s_b2,s_b3,s_b4;}S_un_b;
struct{u_shorts_w1,s_w2;}S_un_w;
u_longS_addr;
}S_un;
首先阐述in_addr的含义,很显然它是一个存储ip地址的联合体,有三种表达方式:
◆第一种用四个字节来表示IP地址的四个数字;
◆第二种用两个双字节来表示IP地址;
◆第三种用一个长整型来表示IP地址。
给in_addr赋值的一种最简单方法是使用inet_addr函数,它可以把一个代表IP地址的字符串赋值转换为in_addr类型,如
addrto.sin_addr.s_addr=inet_addr("192.168.0.2");
其反函数是inet_ntoa,可以把一个in_addr类型转换为一个字符串。
sockaddr_in的含义比in_addr的含义要广泛,其各个字段的含义和取值如下:
Ø第一个字段short sin_family,代表网络地址族,如前所述,只能取值AF_INET;
Ø第二个字段u_shortsin_port,代表IP地址端口,由程序员指定;
Ø第三个字段struct in_addrsin_addr,代表IP地址;
Ø第四个字段char sin_zero[8],很搞笑,是为了保证sockaddr_in与SOCKADDR
型的长度相等而填充进来的字段。
以下代表指明了广播地址,端口号为7861的一个地址:
sockaddr_inaddrto; //发往的地址
memset(&addrto,0,sizeof(addrto));
addrto.sin_family=AF_INET; //地址类型为internetwork
addrto.sin_addr.s_addr=INADDR_BROADCAST;//设置ip为广播地址
addrto.sin_port=htons(7861); //端口号为7861
6)发送和接收函数
在Socket中有两套发送和接收函数,一是sendto和recvfrom;二是send和recv。
前一套在函数参数中要指明地址;而后一套需要先将套接字和一个地址绑定,然后直接发送和接收,不需绑定地址。
sendto的定义如下:
intPASCALFARsendto(SOCKETs,constcharFAR*buf,intlen,intflags,const
structsockaddrFAR*to,inttolen);
第一个参数就是套接字;
第二个参数是要传送的数据指针;
第三个参数是要传送的数据长度(字节数);
第四个参数是传送方式的标识,如果不需要特殊要求则可以设置为0,其它值请参考MSDN;
第五个参数是目标地址,注意这里使用的是sockaddr的指针;
第六个参数是地址的长度;返回值为整型,如果成功,则返回发送的字节数,失败则返回SOCKET_ERROR。
send和recv是用来发送和接收数据的两个重要函数。
send只能在已经连接的状态下使用,而recv可以面向连接和非连接的状态下使用。
send的定义如下:
intWSAAPIsend(SOCKETs,constcharFAR*buf,
intlen,intflags);
其参数的含义和sendto中的前四个参数一样。
而recv的定义如下:
intWSAAPIrecv(SOCKETs,charFAR*buf,
intlen,intflags);
其参数含义与send中的参数含义一样。
成绩:
2015-2016学年第2学期
《计算机网络》课程设计
DAY3:
题目:
服务器端、客户端设计
学院名称:
班级学号:
学生姓名:
教师姓名:
2016年7月
1.设计原理
2.具体设计
(1)socket函数:
为了执行网络输入输出,一个进程必须做的第一件事就是调用socket函数获得一个文件描述符。
#include
intsocket(intfamily,inttype,intprotocol);
返回:
非负描述字---成功 -1---失败
第一个参数指明了协议簇,目前支持5种协议簇,最常用的有AF_INET(IPv4协议)和AF_INET6(IPv6协议);第二个参数指明套接口类型,有三种类型可选:
SOCK_STREAM(字节流套接口)、SOCK_DGRAM(数据报套接口)和SOCK_RAW(原始套接口);如果套接口类型不是原始套接口,那么第三个参数就为0。
(2)connect函数:
当用socket建立了套接口后,可以调用connect为这个套接字指明远程端的地址;如果是字节流套接口,connect就使用三次握手建立一个连接;如果是数据报套接口,connect仅指明远程端地址,而不向它发送任何数据。
#include
intconnect(intsockfd,conststructsockaddr*addr,socklen_taddrlen);
返回:
0---成功 -1---失败
第一个参数是socket函数返回的套接口描述字;第二和第三个参数分别是一个指向套接口地址结构的指针和该结构的大小。
这些地址结构的名字均已“sockaddr_”开头,并以对应每个协议族的唯一后缀结束。
以IPv4套接口地址结构为例,它以“sockaddr_in”命名,定义在头文件;以下是结构体的内容:
structin_addr{
in_addr_ts_addr; /*IPv4地址*/
};
structsockaddr_in{
uint8_tsin_len;/*无符号的8位整数*/
sa_family_tsin_family;
/*套接口地址结构的地址簇,这里为AF_INET*/
in_port_tsin_port;/*TCP或UDP端口*/
structin_addrsin_addr;
charsin_zero[8];
};
(3)bind函数:
为套接口分配一个本地IP和协议端口,对于网际协议,协议地址是32位IPv4地址或128位IPv6地址与16位的TCP或UDP端口号的组合;如指定端口为0,调用bind时内核将选择一个临时端口,如果指定一个通配IP地址,则要等到建立连接后内核才选择一个本地IP地址。
#include
intbind(intsockfd,conststructsockaddr*server,socklen_t