|
练习一:编辑并发送UDP
1、打开数据包编辑器,在工具栏选择“新建”,建立一个以太网帧;
2、观察运行结果,获得本机的以太网地址:
(a)源MAC地址”和“目的MAC地址”字段,注意:当选择的目的主机与本机不在同一
子网的情况,目的MAC地址该怎样填写
(b)“类型或长度”字段值应为:0800(即IP协议的类型值)
3、填写IP协议头信息:
注意协议字段,即上层协议类型应为17(UDP协议的类型为17);
4、填写UDP协议信息:
(a)16位源端口号:自选
(b)16位目的端口号:自选
(c)数据字段:可有可无
(d)16位UDP长度:UDP报头长度(8)与UDP数据长度之和
(e)校验和:覆盖UDP首部(含伪首部)和数据两部分。请先根据参考原理(3)的内
容进行手工计算,然后利用数据包编辑器来计算(方法二),比较二者的结果,
检验手工计算结果的正确性。
方法一:手工计算。
按照参考原理(3)中介绍的内容,计算好UDP伪首部和首部中的各项
值,然后按16bit进行反码求和(方法同计算IP校验和),将结果填入相
应字段。
方法二:利用数据包编辑器来计算。步骤为:
①将UDP长度填写到16位UDP校验和字段中作为伪首部中UDP长度字段
  值;
②选中IP首部中的32位源IP地址和32位目的IP地址作为UDP伪首部中的
  32位源IP地址和32位目的IP地址;
③选中IP首部中8位的协议字段作为UDP伪首部中的8位的协议字段;
④在8位的协议字段之前选择一个8位的0作为UDP伪首部中的8位0;
⑤再选中UDP首部的及数据各字段;
⑥点击鼠标右键,选择“计算校验和”;
⑦将得到的校验和值填写到16位UDP校验和字段。
下面是一个计算UDP校验和的一个例子:
一个不含数据部分的UDP数据报的十六进制对照表如下:
00 01 02 03 04 05 06 07 08 09 0A 0B 08 00 45 00
00 4F 94 48 40
00 80 11 E4 9D
C0 A8 00 20 C0 A8
00 52 00 00 00 00 00 08 00 08
其中黑体部分为用来计算校验和的UDP伪首部和UDP首部,其中:
00 11(十进制的17):为UDP伪首部中8位的0和8位的协议字段;
C0 A8 00 20:为UDP伪首部中32位源IP地址;
C0 A8 00 52:为UDP伪首部中32位目的IP地址;
00 00 00 00 00 08 00 08:为8字节的UDP首部;
由于缺少伪首部中16位UDP长度,故该值暂时存放在16位UDP校验和字段 中,在本例中该值为00 08;
对上述选中部分计算校验和即可。
5、如果要发送多个UDP数据报,可重复上述步骤,并可在多帧编辑器中设置每一帧的发
送次数和发送每帧的时间间隔;
6、点击工具栏或菜单栏中的“发送”,在弹出菜单上选择“发送”按钮,发送UDP报文;
7、在监控机一端截获相应的报文并分析。
练习二:编辑并发送UDP广播包
1、实验步骤同上; 注意:以太网协议首部中的目的MAC地址应怎样填写?
IP首部中的目的IP地址该怎样填写?
2、在监控机一端截获相应的报文并分析。
练习三:运行netstat命令
1、在DOS命令行方式下运行:netstat –s 显示每个协议的使用状态,观察UDP协议的
使用情况。
2、在DOS命令行方式下运行:netstat –a 显示所有主机的端口号,观察与UDP协议相
关的内容。
练习四:运行ipconfig命令
1、在DOS命令提示符下运行:
ipcofig /displaydns
2、 观察运行结果。
练习五:运行Winsock网络程序
设计一个简单的Winsock网络程序,模拟UDP数据报,加深对DNS作用的理解。
1、启动Visual C++,进入集成开发环境;
2、 建立一个“Win32 Consol Application”类型的工程,工程名自拟;
3、 在该工程下,新建一个源程序文件,即选择“C++ Source File”,文件名自拟;
4、输入以下源程序(注释部分不必输入):
//////////////////////////////////////////////////////////////////////////
//本程序的功能为: //
//(1)获取本机名(gethostname()); //
//(2)获得给定主机名的IP地址(gethostbyname()); //
//(3)获得给定IP地址的主机名(gethostbyaddr()). //
//////////////////////////////////////////////////////////////////////////
/*头文件*/
#include <winsock.h>
#include <stdio.h>
#include <string.h>
int main()
{
/*初始化 windows sockets API*/
WORD wVersionRequested = MAKEWORD(1, 1);
WSADATA wsaData;
if (WSAStartup(wVersionRequested, &wsaData)) {
printf("WSAStartup failed %s\n", WSAGetLastError());
return -1;
}
/* 获得本主机名*/
char hostname[256];
int res = gethostname(hostname, sizeof(hostname));
/*错误处理*/
if (res != 0) {
printf("Error: %u\n", WSAGetLastError());
return -1;
}
/*打印本主机名字*/
printf("本主机名为:%s\n", hostname);
/*输入一个主机的域名,可以为本机也可以为其他主机*/
printf("请输入一个主机域名:");
scanf("%s",hostname);
/* 利用主机名获得主机的地址信息 */
hostent* pHostent = gethostbyname(hostname);
/*错误处理*/
if (pHostent==NULL) {
printf("Error: %u\n", WSAGetLastError());
return -1;
}
/* 解析返回的主机地址信息:别名、地址类型、地址长度,并打印*/
hostent& he = *pHostent;
printf("name=%s\naliases=%s\naddrtype=%d\nlength=%d\n",
he.h_name, he.h_aliases, he.h_addrtype, he.h_length);
/*打印主机每一个网卡的IP地址*/
sockaddr_in sa;
for (int nAdapter=0; he.h_addr_list[nAdapter]; nAdapter++) {
memcpy ( &sa.sin_addr.s_addr, he.h_addr_list[nAdapter],he.h_length);
/* 输出机器的 IP地址并以字符 串的形式显示出来.*/
printf("Address: %s\n", inet_ntoa(sa.sin_addr));
}
printf("\n");
/*输入一个服务器的IP地址*/
unsigned long addr;
char hostaddr[50];
printf("请输入服务器IP地址:");
scanf("%s",hostaddr);
/*将IP地址转化为网络字节序*/
addr=inet_addr(hostaddr);
/*利用IP地址获得主机名*/
pHostent=gethostbyaddr((char *)&addr,4,AF_INET);
/*错误处理*/
if (pHostent==NULL) {
printf("Error: %u\n", WSAGetLastError());
return -1; }
hostent& he1 = *pHostent;
/*打印返回的地址信息,注意主机名字信息*/
printf("主机名为:%s\naliases=%s\naddrtype=%d\nlength=%d\n",
he.h_name, he.h_aliases, he.h_addrtype, he.h_length);
/* 结束 windows sockets API*/
WSACleanup();
return 0;
}
6、使用Winsock函数的程序必须与 WS2_32.LIB进行链接,而Visual C++集成开发环
境的缺省链接库中没有此项,因此要把ws2_32.lib加入到链接库的列表里面。
具体步骤是:
(a)选择“工程”菜单下的“设置”项。
(b)在弹出页面中选择“Link”一项。
(c)将“ws2_32.lib”加入“L对象/库模块”列表当中。
7、编译、连接并运行程序。
8、观察程序运行的结果,体会程序中几个主要函数的作用。
练习六:反复运行上述程序,可以输入以下域名:
www.jlu.edu.cn
mail.jlu.edu.cn
www.sina.com
www.microsoft.com
……
在监控机端捕获数据并分析说明:
1、名字解析器使用传输层的哪一协议来处理查询请求?
2、本地名字服务员的IP地址是什么?
3、名字服务员进程的端口号是什么?
4、随便输入一个不带后缀的主机名(如:aaa),观察捕获到的数据。
|