欢迎来到装配图网! | 帮助中心 装配图网zhuangpeitu.com!
装配图网
ImageVerifierCode 换一换
首页 装配图网 > 资源分类 > PPT文档下载
 

通信网络程序设计(王晓东西电版)第7章直接网络编程

  • 资源ID:22134418       资源大小:912.50KB        全文页数:255页
  • 资源格式: PPT        下载积分:14.9积分
快捷下载 游客一键下载
会员登录下载
微信登录下载
三方登录下载: 微信开放平台登录 支付宝登录   QQ登录   微博登录  
二维码
微信扫一扫登录
下载资源需要14.9积分
邮箱/手机:
温馨提示:
用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
支付方式: 支付宝    微信支付   
验证码:   换一换

 
账号:
密码:
验证码:   换一换
  忘记密码?
    
友情提示
2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

通信网络程序设计(王晓东西电版)第7章直接网络编程

1第 7章 直 接 网 络 编 程7.1 以 太 网 工 作 原 理7.2 基 于 Winpcap的 网 络 编 程7.3 原 始 套 接 字 编 程7.4 基 于 libnet的 网 络 编 程7.5 基 于 NDIS的 网 络 编 程小 结 2 前面介绍的基于三大协议的网络编程能够满足常规网络编程的要求,可以实现普通网络通信应用的设计,但是却都无法直接访问网络层和数据链路层。随着计算机网络复杂性及规模的不断增长,迫切需要提供一些网络工具能够在网络层和数据链路层面上分析、诊断和测试网络,保证网络通信的正常运行和通信安全。由于这些网络诊断测试和安全工具工作在网络较低的层次(链路层或网络层),因而不能采用常规的网络编程方法。本章将介绍几种不同的直接网络编程方法来实现这种需求。通过对本章的学习,可以使读者进一步了解到网络低层协议的运行机理,从更深层次掌握网络编程方法。 3 本章在剖析以太网的工作原理的基础上,首先简要介绍基于Winpcap的网络数据包捕获编程,然后介绍基于原始套接字的网络编程,鉴于原始套接字编程数据包构造方面的局限,又介绍了基于libnet的数据包构造编程,最后介绍了基于NDIS的passtru数据包过滤编程方法。这些编程接口为用户开发网络嗅探、协议分析、网络攻击、入侵检测、防火墙等复杂网络应用提供了重要工具。 4 直 接 网 络 编 程 技 术 与 网 络 链 路 层 协 议 、 网 卡 工 作 模 式 以及 网 卡 驱 动 模 型 有 密 切 关 系 , 这 三 项 技 术 解 决 了 数 据 从 网 络到 主 机 , 再 到 应 用 的 传 递 问 题 。 在 展 开 编 程 设 计 前 , 首 先 对这 三 方 面 的 知 识 内 容 进 行 简 要 介 绍 。7.1 以 太 网 工 作 原 理 5 7.1.1 CSMA/CD协 议 OSI模 型 中 , 网 络 层 的 下 面 是 链 路 层 , 这 一 层 最 重 要 的功 能 是 确 定 由 谁 占 有 信 道 , 以 太 网 采 用 CSMA/CD协 议 实 现该 功 能 。 在 常 见 的 网 络 总 线 型 和 环 型 拓 扑 中 , 网 络 上 的 设 备必 须 共 享 传 输 线 路 (总 线 系 统 ), 为 解 决 同 一 时 间 几 个 设 备 同时 争 用 传 输 介 质 的 难 题 , 需 要 有 某 种 访 问 控 制 方 式 , 以 便 协调 各 设 备 访 问 介 质 的 顺 序 , 从 而 无 障 碍 地 在 设 备 之 间 交 换 数据 。 6 总 线 型 结 构 中 (如 图 7-1所 示 ), 每 个 站 (网 络 节 点 )都 能 独立 地 决 定 帧 的 发 送 , 若 两 个 或 多 个 站 同 时 进 行 发 送 , 就 会 产生 冲 突 , 而 且 同 时 发 送 的 所 有 帧 都 会 出 错 。 因 此 , 一 个 用 户发 送 信 息 的 成 功 与 否 在 很 大 程 度 上 取 决 于 判 断 总 线 是 否 空 闲的 算 法 以 及 两 个 不 同 节 点 同 时 发 送 的 分 组 发 生 冲 突 时 所 使 用和 中 断 传 输 的 方 法 。 在 随 机 访 问 方 式 中 , 常 用 的 争 用 总 线 技术 为 CSMA/CD(Carrier Sense Multiple Access/Collision Detect,遵 循 IEEE 802.3标 准 ), 它 是 载 波 监 听 多 路 访 问 (CSMA)和 冲突 检 测 (CD)两 种 技 术 的 结 合 。 7 CSMA技 术 也 叫 做 先 听 后 说 (Listen Before Talk, LBT)技 术 ,这 种 技 术 总 是 希 望 传 输 的 站 首 先 对 信 道 进 行 监 听 以 确 定 是 否有 别 的 站 在 传 输 。 如 果 信 道 空 闲 , 该 站 可 以 传 输 ; 否 则 , 该站 先 避 让 一 段 时 间 后 再 尝 试 。 由 此 , LBT就 需 要 有 一 种 退 避算 法 来 决 定 退 让 时 间 , CSMA/CD常 用 的 退 避 算 法 有 非 坚 持 、1-坚 持 、 P-坚 持 三 种 。 8图 7-1 总 线 型 结 构 9 1 非 坚 持 算 法 非 坚 持 算 法 规 则 规 定 : 假 如 媒 体 是 空 闲 的 , 则 可 以立 即 发 送 。 假 如 媒 体 是 忙 的 , 则 等 待 一 个 由 概 率 分 布 决定 的 随 机 重 发 延 迟 后 , 再 重 复 前 一 步 骤 。 采 用 随 机 的 重 发 延 迟 时 间 可 以 减 少 冲 突 发 生 的 可 能 性 。非 坚 持 算 法 的 缺 点 是 : 即 使 有 几 个 节 点 都 有 数 据 要 发 送 , 但由 于 大 家 都 在 延 迟 等 待 过 程 中 , 致 使 媒 体 仍 可 能 处 于 空 闲 状态 , 因 此 使 用 率 降 低 。 10 2 1-坚 持 算 法 1-坚 持 算 法 规 则 规 定 : 假 如 媒 体 空 闲 的 , 则 可 以 立即 发 送 。 假 如 媒 体 是 忙 的 , 则 继 续 监 听 , 直 至 检 测 到 媒体 是 空 闲 , 则 立 即 发 送 。 假 如 有 冲 突 (在 一 段 时 间 内 未 收到 肯 定 的 回 复 ), 则 等 待 一 段 随 机 量 的 时 间 后 重 复 步 骤 。 这 种 算 法 的 优 点 是 : 只 要 媒 体 空 闲 , 站 点 就 立 即 可 发 送 ,避 免 了 媒 体 利 用 率 的 损 失 ; 其 缺 点 是 : 假 若 有 两 个 或 两 个 以上 的 站 点 都 有 数 据 要 发 送 , 冲 突 就 不 可 避 免 。 11 3 P-坚 持 算 法 P-坚 持 算 法 规 则 规 定 : 监 听 总 线 , 假 如 媒 体 是 空 闲的 , 传 输 概 率 为 P, 以 1-P的 概 率 延 迟 一 个 时 间 单 位 。 一 个 时间 单 位 通 常 等 于 最 大 传 播 时 延 的 2倍 。 延 迟 一 个 时 间 单 位后 , 再 重 复 步 骤 。 假 如 媒 体 是 忙 的 , 继 续 监 听 直 至 媒体 空 闲 并 重 复 步 骤 。 P-坚 持 算 法 是 一 种 既 能 像 非 坚 持 算 法 那 样 减 少 冲 突 , 又能 像 1-坚 持 算 法 那 样 减 少 媒 体 空 闲 时 间 的 折 中 方 案 。 问 题 在于 如 何 选 择 P的 值 , 这 要 考 虑 到 避 免 重 负 载 下 系 统 处 理 于 不稳 定 状 态 。 12 在 CSMA中 , 由 于 通 道 的 传 播 延 迟 , 当 两 个 站 点 都 监 听到 总 线 上 没 有 存 在 信 号 而 发 送 帧 时 , 仍 会 发 生 冲 突 。 由 于CSMA算 法 没 有 冲 突 检 测 功 能 , 即 使 冲 突 已 发 生 , 也 仍 然 要将 已 破 坏 的 帧 发 送 完 , 使 总 线 的 利 用 率 降 低 。 一 种 CSMA的改 进 方 案 是 使 站 点 在 传 输 时 间 继 续 监 听 媒 体 , 一 旦 网 络 检 测到 冲 突 (Collision Detect), 就 立 即 停 止 发 送 , 并 向 总 线 上 发 一串 短 的 阻 塞 报 文 (Jam), 通 知 总 线 上 各 站 已 发 生 冲 突 , 这 样通 道 容 量 不 致 因 白 白 传 送 已 受 损 的 帧 而 浪 费 , 可 以 提 高 总 线的 利 用 率 , 这 就 是 CSMA/CD。 CSMA/CD很 好 地 解 决 了 链 路层 信 道 竞 争 的 问 题 , 使 得 数 据 可 以 顺 利 地 发 送 到 网 络 上 指 定的 站 。 13 根 据 IEEE 802标 准 , 数 据 链 路 层 进 一 步 又 可 划 分 为 逻 辑链 路 层 LLC(Logical Link Control)子 层 和 介 质 访 问 控 制 MAC子 层 。 前 者 负 责 识 别 网 络 层 协 议 并 对 它 们 进 行 封 装 ; 后 者 负责 实 现 CSMA/CD或 类 似 的 访 问 控 制 (如 Token令 牌 方 式 )。 14 7.1.2 NIC接 收 模 式 虽 然 CSMA/CD协 议 解 决 了 网 络 总 线 的 信 道 资 源 利 用 的重 要 问 题 , 但 在 站 节 点 上 , 数 据 想 要 透 过 物 理 层 和 链 路 层 到达 主 机 的 更 上 层 直 至 应 用 , 还 离 不 开 一 个 重 要 软 硬 件 设 备 网 卡 。 网 卡 即 网 络 适 配 器 (Network Interface Card, NIC),是 局 域 网 中 最 基 本 的 部 件 之 一 , 它 是 连 接 计 算 机 与 网 络 的 关键 设 备 , 无 论 是 双 绞 线 连 接 、 同 轴 电 缆 连 接 还 是 光 纤 连 接 ,都 必 须 借 助 于 网 卡 才 能 实 现 主 机 与 网 络 间 的 数 据 通 信 。 15 从 网 络 通 信 模 型 角 度 来 看 , 一 块 网 卡 包 括 OSI模 型 的 两个 层 物 理 层 和 数 据 链 路 层 。 物 理 层 定 义 了 数 据 传 送 与 接收 所 需 要 的 电 与 光 信 号 、 线 路 状 态 、 时 钟 基 准 、 数 据 编 码 和电 路 等 , 并 向 数 据 链 路 层 设 备 提 供 标 准 接 口 , 我 们 编 程 时 并不 关 心 这 些 。 数 据 链 路 层 则 提 供 寻 址 机 构 、 数 据 帧 的 构 建 、数 据 差 错 检 查 、 传 送 控 制 、 向 网 络 层 提 供 标 准 的 数 据 接 口 等功 能 , 这 是 我 们 进 行 直 接 网 络 编 程 所 必 须 了 解 的 。 在 这 两 个层 面 上 , 可 以 将 网 卡 的 功 能 总 结 为 “ 来 ” 和 “ 去 ” 两 条 : 一是 接 收 网 络 上 其 他 设 备 传 过 来 的 帧 , 并 将 帧 重 新 组 合 成 数 据 ,发 送 到 所 在 的 电 脑 的 网 络 协 议 栈 上 层 ; 二 是 将 电 脑 的 数 据 封装 为 帧 , 并 通 过 网 线 (对 无 线 网 络 来 说 就 是 电 磁 波 )将 数 据 发送 到 网 络 上 去 。 16 结 合 CSMA/CD的 工 作 原 理 进 行 分 析 , 要 想 实 现 信 道 的竞 争 占 用 , 网 卡 必 须 能 够 监 听 到 信 道 中 所 有 的 传 输 信 号 , 这种 接 收 模 式 称 为 混 杂 (Promiscuous)模 式 。 正 常 情 况 下 , 网 卡工 作 在 非 混 杂 模 式 下 , 接 收 传 输 来 的 数 据 的 具 体 过 程 是 : 网卡 检 查 数 据 帧 目 的 MAC地 址 , 根 据 计 算 机 上 的 网 卡 驱 动 程序 设 置 的 接 收 模 式 判 断 接 收 与 否 。 如 接 收 , 则 产 生 中 断 信 号通 知 CPU; 如 不 接 收 , 则 将 数 据 帧 丢 弃 。 CPU得 到 中 断 信 号产 生 中 断 , 操 作 系 统 接 收 数 据 。 在 混 杂 模 式 下 , 上 述 MAC地 址 检 查 的 步 骤 会 被 跳 过 , 因 而 所 有 的 链 路 层 帧 都 会 被 接 收 ,若 进 一 步 对 截 获 的 帧 进 行 解 析 , 网 络 层 、 传 输 层 的 数 据 包 也可 以 容 易 地 获 得 。 17 总 结 起 来 , 网 卡 共 有 如 下 四 种 接 收 模 式 : (1) 广 播 方 式 : 能 够 接 收 网 络 中 的 广 播 信 息 。 (2) 组 播 方 式 : 能 够 接 收 组 播 数 据 。 (3) 直 接 方 式 : 只 有 目 的 网 卡 才 能 接 收 该 数 据 。 (4) 混 杂 模 式 : 能 够 接 收 通 过 它 的 一 切 数 据 , 而 不 管 该数 据 是 否 是 传 给 它 的 。 本 章 重 点 讲 述 混 杂 模 式 , 有 很 多 方 法 可 以 将 网 卡 设 置 成混 杂 模 式 , 以 下 函 数 采 用 套 接 字 I/O命 令 ioctlsocket(见 5.2.3节 )将 套 接 字 设 置 成 混 杂 模 式 : ioctlsocket(sRaw,SIO_RCVALL, if (d-description) printf( (%s)n, d-description); else 80 printf( (No description available)n); if(i=0) printf(nNo interfaces found! Make sure WinPcap is installed.n); return -1; printf(Enter the interface number (1-%d):,i); scanf(%d, if(inum i) 81 printf(nInterface number out of range.n); pcap_freealldevs(alldevs); /释 放 设 备列 表 return -1; /跳 转 到 已 选 择 的 网 络 适 配 器 for(d=alldevs, i=0; inext, i+); /打 开 网 络 接 口 82 if ( (adhandle= pcap_open_live( d-name,/网 络 设 备 名 65536, /数 据 包 的 捕 获 部分 1, /混 合 模 式 1000, /读 超 时 值 errbuf /错 误 信 息 缓 存 区 ) ) = NULL) fprintf(stderr,nUnable to open the adapter. %s is not supported by WinPcapn); 83 pcap_freealldevs(alldevs); return -1; printf(nlistening on %s.n, d-description); pcap_freealldevs(alldevs); /释 放 设 备列 表 pcap_loop(adhandle, 0, packet_handler, NULL); /开 始 捕 获 数 据 包 return 0; 84 void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) /回 调 函 数 struct tm *ltime; char timestr16; / 转 换 时 戳 格 式 85 ltime = localtime( strftime( timestr, sizeof timestr, %H:%M:%S, ltime); printf(%s,%.6d len:%dn, timestr, header-ts.tv_usec, header-len); 86 2 过 滤 接 收 Winpcap可 以 对 网 络 数 据 包 进 行 过 滤 (这 里 的 过 滤 只 是 对本 应 用 程 序 的 过 滤 , 并 不 是 把 数 据 包 从 网 络 中 过 滤 掉 , 与7.5节 介 绍 的 内 容 不 同 ), 使 应 用 程 序 可 以 有 选 择 地 接 收 感 兴趣 的 数 据 包 。 用 于 过 滤 数 据 包 的 函 数 是 pcap_compile()和pcap_setfilter()。 函 数 pcap_compile()编 译 过 滤 器 , 它 把 一 个高 层 的 布 尔 表 达 式 编 译 生 成 一 个 低 层 过 滤 器 二 进 制 代 码 。 函数 pcap_setfilter()为 捕 获 应 用 程 序 设 置 过 滤 器 。 下 面 的 代 码 显示 如 何 编 译 和 设 置 过 滤 器 。 程 序 中 传 递 给 pcap_compile()的过 滤 器 表 达 式 是 “ ip and tcp”, 表 示 只 接 受 IPv4和 TCP的 数 据包 。 87 一 般 而 言 , 应 用 程 序 要 从 描 述 网 络 接 口 的 结 构 pcap_if中取 得 子 网 掩 码 (netmask), 因 为 有 一 些 由 pcap_compile()创 建的 过 滤 器 需 要 用 到 子 网 掩 码 。 if(d-addresses != NULL) /如 果 有 子 网 掩 码 , 则 取得 子 网 掩 码 netmask=(struct sockaddr_in *)(d-addresses-netmask)-sin_addr.S_un.S_addr; else /如 果 没 有 子 网 掩 码 , 则 认 为 是 一个 C类 网 络 88 netmask=0 xffffff; /编 译 过 滤 器 if(pcap_compile(adhandle, pcap_freealldevs(alldevs); /释 放 设 备 列 表 return -1; 89 /设 置 过 滤 器 if(pcap_setfilter(adhandle, pcap_freealldevs(alldevs); return -1; 90 3 流 量 统 计 为 取 得 网 络 流 量 的 统 计 信 息 , 程 序 员 应 打 开 网 络 接 口 ,并 用 函 数 pcap_setmode()设 置 成 统 计 模 式 。 下 面 的 代 码 利 用统 计 模 式 来 监 视 网 络 中 的 TCP流 量 。 #include #include #include void usage(); void dispatcher_handler( u_char *,const struct pcap_pkthdr *,const u_char *); 91 void main(int argc, char *argv) pcap_t *fp; char errorPCAP_ERRBUF_SIZE; struct timeval st_ts; u_int netmask; struct bpf_program fcode; if (argc != 2) /检 查 命 令行 参 数 92 usage(); return; if(fp = pcap_open_live(argv1, 100, 1, 1000, error) = NULL)/打 开 网 络 接 口 fprintf(stderr,nError opening adapter: %sn, error); return; 93 netmask=0 xffffff; /不 考 虑 子网 掩 码 if(pcap_compile(fp, return; 94 if(pcap_setfilter(fp, /计 算 速 率 bps Bps.QuadPart=(*(LONGLONG*)(pkt_data + 8) * 8 * 1000000) / (delay); 97 /计 算 速 率 (每 秒 发 送 包 的 个 数 )pps Pps.QuadPart=(*(LONGLONG*)(pkt_data) * 1000000) / (delay); ltime=localtime( strftime( timestr, sizeof timestr, %H:%M:%S, ltime); /显 示 时 戳 printf(%s , timestr); /显 示 采 样 值 printf(BPS=%I64u , Bps.QuadPart); 98 printf(PPS=%I64un, Pps.QuadPart); /存 储 当 前 时 戳 old_ts-tv_sec=header-ts.tv_sec; old_ts-tv_usec=header-ts.tv_usec; void usage() printf(nShows the TCP traffic load, in bits per second and packets per second.n ); 99 printf(nUsage:n); printf(t tcptop adaptern); exit(0); 自 Wincap开 始 投 入 使 用 截 至 目 前 , 已 经 更 新 了 多 个 版 本 ,为 了 确 保 旧 的 编 译 器 (如 VC6.0)对 新 版 本 Wincap(4.0.1之 后 )的调 用 , 需 为 系 统 装 适 合 的 PSDK。 100 虽 然 Winpcap本 身 具 有 数 据 包 的 构 造 功 能 , 但 是 使 用 起来 并 不 方 便 , 通 常 可 以 采 用 原 始 套 接 字 和 基 于 libnet的 编 程技 术 (参 见 7.4节 )。7.3 原 始 套 接 字 编 程 101 原 始 套 接 字 既 可 以 对 底 层 的 传 输 协 议 加 以 控 制 , 也 可 以对 IP头 信 息 进 行 实 际 的 操 作 , 通 过 它 还 可 以 模 拟 一 些 IP的 实用 工 具 , 如 tracert和 ping等 。 原 始 套 接 字 (raw socket)是 使 用SOCK_RAW这 个 套 接 字 类 型 来 创 建 的 , 目 前 , WinSock 2.2提 供 了 对 它 的 支 持 。 利 用 原 始 套 接 字 可 访 问 位 于 低 层 的 网 络协 议 。 102 7.3.1 原 始 套 接 字 原 理 本 节 重 点 讨 论 利 用 IP层 协 议 的 Internet控 制 消 息 协 议(ICMP)进 行 原 始 套 接 字 编 程 。 为 了 说 明 问 题 , 运 用 这 种 原 始套 接 字 来 设 计 实 现 ping和 tracert程 序 。 ping这 个 应 用 程 序 探 测到 某 个 主 机 的 路 由 是 否 有 效 和 畅 通 , 看 看 对 方 的 机 器 是 否 会作 出 响 应 。 对 程 序 开 发 者 来 说 , 经 常 要 用 到 一 种 程 序 化 的 方法 , 以 便 判 断 一 台 机 器 是 否 “ 活 动 ” , 网 络 数 据 能 否 抵 达 它 。 tracert是 基 于 ping的 扩 展 。 103 创 建 原 始 套 接 字 可 用 socket或 WSASocket函 数 。 在 套 接字 的 创 建 过 程 中 , 必 须 自 行 设 定 SOCK_RAW标 志 。 下 述 代码 片 断 解 释 了 如 何 将 ICMP作 为 一 种 基 层 IP协 议 来 完 成 一 个原 始 套 接 字 的 创 建 : SOCKET s; s=socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if(s=INVALID_SOCKET) /创 建 套 接 字 失 败 104 在 完 成 了 原 始 套 接 字 的 创 建 之 后 , 就 可 以 在 发 送 及 接 收调 用 中 使 用 对 应 的 套 接 字 句 柄 了 。 创 建 原 始 套 接 字 时 , 无 论是 否 设 定 了 IP_HDRINCL选 项 , IP头 都 会 包 含 在 接 收 到 的 任何 返 回 数 据 中 。 上 述 代 码 中 采 用 的 是 ICMP。 当 使 用 IGMP、 UDP、 IP或者 原 始 IP时 , 分 别 设 置 IPPROTO_IGMP、 IPPROTO_UDP、IPPROTO_IP或 IPPROTO_RAW即 可 。 但 值 得 注 意 的 是 ,Windows 95无 法 使 用 原 始 套 接 字 ; 在 Windows 98/NT的 操 作系 统 中 , 创 建 原 始 套 接 字 时 , 只 能 使 用IGMP(IPPROTO_IGMP)和 ICMP(IPPROTO_ICMP)两 种 协 议 ; 105 而 Windows 2000/XP在 前 者 基 础 上 还 能 够 处 理IP(IPPROTO_RAW)、 TCP(IPPROTO_TCP)及UDP(IPPROTO_UDP)。 由 于 使 用 原 始 套 接 字 可 以 控 制 基 层 传 输 机 制 , 势 必 会 存在 潜 在 的 安 全 隐 患 , 因 此 , 在 Windows NT/2000/XP上 , 只 有属 于 “ 管 理 员 ” (administrator)组 的 成 员 , 才 有 权 创 建 类 型 为SOCK_RAW的 套 接 字 。 要 绕 过 这 一 限 制 , 可 禁 止 对 原 始 套接 字 的 安 全 检 查 。 方 法 是 在 注 册 表 中 创 建 变 量HKEY_LOCAL_MACHINESystemCurrentControlSetServicesAfdParameters DisableRawSecurity, 并 将 它 的 值 设 为 1(DWORD类 型 ),然 后 重 新 启 动 计 算 机 。 106 此 外 , 原 始 套 接 字 可 先 使 用 ioctlsocket()函 数 将 套 接 字 设置 为 SIO_RCVALL(见 附 录 6), 再 使 用 recv()函 数 , 接 收 经 过本 地 网 卡 的 所 有 IP封 包 , 从 而 实 现 简 单 的 网 络 抓 包 功 能 。 这里 不 做 过 多 介 绍 。 107 7.3.2 原 始 套 接 字 ping程 序 设 计 原 始 套 接 字 的 典 型 应 用 就 是 ping程 序 的 设 计 , 下 面 将 进行 分 析 介 绍 。 1 ping程 序 原 理 ping程 序 可 用 于 判 断 一 个 特 定 的 主 机 是 否 处 于 活 动 状 态 。ping程 序 的 实 现 方 法 是 主 机 先 向 远 程 计 算 机 发 出 ICMP回 应 请求 , 远 程 计 算 机 处 理 这 个 请 求 , 然 后 生 成 一 条 回 应 应 答 消 息 ,再 通 过 网 络 传 回 给 发 送 主 机 。 假 如 由 于 某 些 方 面 的 原 因 不 能抵 达 目 标 主 机 , 就 会 生 成 对 应 的 ICMP错 误 消 息 (比 如 “ 目 标主 机 不 可 到 达 ” ), 并 由 那 个 路 径 上 某 处 的 一 个 路 由 器 返 回 ; 108 假 如 与 远 程 主 机 的 物 理 性 链 接 并 不 存 在 问 题 , 但 远 程 主 机 已经 关 机 或 没 有 设 置 对 网 络 事 件 作 出 响 应 , 便 需 由 自 己 的 程 序来 执 行 超 时 检 查 。 109 2 ping程 序 设 计 ping程 序 设 计 的 步 骤 如 下 : (1) 创 建 类 型 为 SOCK_RAW的 一 个 套 接 字 , 同 时 设 定协 议 IPPROTO_ICMP。 (2) 创 建 并 初 始 化 ICMP头 。 (3) 调 用 sendto()或 WSASendto()函 数 , 将 ICMP请 求 发 给远 程 主 机 。 (4) 调 用 recvfrom()或 WSARecvfrom()函 数 , 接 收 任 何ICMP响 应 。 110 接 下 来 的 代 码 示 范 了 如 何 初 始 化 并 发 送 一 个 ICMP echo请 求 。 #include stdafx.h #include #include #pragma comment(lib,wsock32.lib) DWORD StartSock() /略 , 同 6.3.2节 USHORT checksum(USHORT* buff, int size) 111 unsigned long cksum = 0; while(size1) cksum += *buff+; size -= sizeof(USHORT); /是 奇 数 if(size) cksum += *(UCHAR*)buff; 112 /将 32位 的 cksum高 16位 和 低 16位 相 加 , 然 后 取反 cksum = (cksum 16) + (cksum cksum += (cksum 16); return (USHORT)(cksum); typedef struct icmp_hdr 113 unsigned char icmp_type;/消 息 类 型 unsigned char icmp_code;/代 码 unsigned short icmp_checksum;/校 验 和 unsigned short icmp_id;/唯 一 标 识 unsigned short icmp_sequence; /序 列 号 114 unsigned long icmp_timestamp; /时 间 戳 ICMP_HDR, *PICMP_HDR; int main() /初 始 化 Winsock库 printf(初 始 化 .n); StartSock(); /创 建 原 始 套 接 字 SOCKET sRaw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); 115 char DestIp = 24.84.60.228;/ping的 目 标 IP地 址 int nTime=1000; setsockopt(sRaw, SOL_SOCKET,TRUE ? SO_RCVTIMEO:SO_SNDTIMEO, (char*) /设 置 目 的 地 址 SOCKADDR_IN dest; dest.sin_family = AF_INET; dest.sin_port = htons(0); 116 dest.sin_addr.S_un.S_addr = inet_addr(DestIp); /创 建 ICMP封 包 并 填 充 内 容 char buffsizeof(ICMP_HDR) + 32; ICMP_HDR* pIcmp = (ICMP_HDR*)buff; pIcmp-icmp_type = 8; pIcmp-icmp_code = 0; pIcmp-icmp_id = 8888; pIcmp-icmp_checksum = 0; pIcmp-icmp_sequence = 0; 117 memset( /填 充 数 据 负 载 为 /完 成 ping的 规 定 动 作 USHORTnSeq = 0; char recvBuf1024; SOCKADDR_IN from; int nLen = sizeof(from); for(int nCount = 0;nCounticmp_checksum = 0; pIcmp-icmp_timestamp = GetTickCount(); pIcmp-icmp_sequence = nSeq+; pIcmp-icmp_checksum = checksum(USHORT*)buff, sizeof(ICMP_HDR) + 32); nRet=sendto(sRaw,buff,sizeof(ICMP_HDR) + 32, 0, (SOCKADDR *) 119 if(nRet = SOCKET_ERROR) printf( sendto() failed: %d n, :WSAGetLastError(); return -1; /接 收 并 解 析 ICMP封 包 nRet = recvfrom(sRaw, recvBuf, 1024, 0, (sockaddr*) 120 if(nRet = SOCKET_ERROR) if(WSAGetLastError() = WSAETIMEDOUT) printf( timed outn); continue; printf( recvfrom() failed: %dn, :WSAGetLastError(); return -1; 121 int nTick = :GetTickCount(); ICMP_HDR* pRecvIcmp = (ICMP_HDR*)(recvBuf + 20); printf(Relay from from %s: bytes=%d , inet_ntoa(from.sin_addr),nRet); printf( timeicmp_timestamp); printf( n); :Sleep(500); closesocket(sRaw); return 0; 上 述 程 序 假 设 网 络 为 IPv4网 络 , 通 信 状 态 良 好 且 无 其 他干 扰 (如 安 全 软 件 对 ping的 屏 蔽 )。 123 7.3.3 原 始 套 接 字 tracert程 序 设 计 在 ping程 序 的 基 础 上 , 稍 加 改 进 就 可 以 得 到 tracert程 序 ,本 节 对 tracert程 序 进 行 介 绍 。 1 tracert程 序 原 理 对 IP网 络 来 说 , 另 一 个 非 常 有 用 的 工 具 是 tracert(路 由 追踪 )。 利 用 它 , 我 们 可 侦 测 出 为 抵 达 网 络 内 任 何 一 个 指 定 的主 机 , 中 途 需 经 过 哪 些 路 由 器 , 以 及 它 们 的 IP地 址 是 什 么 。在 Windows操 作 系 统 中 , 一 般 可 以 直 接 运 行 tracert.exe来 调 用tracert。 tracert的 设 计 原 理 是 令 其 向 目 的 地 发 送 一 个 数 据 包 ,并 重 复 递 增 IP的 “ 存 活 时 间 (TTL)”值 (根 据 ICMP协 议 , 数 据包 每 经 过 一 个 路 由 器 , 124 TTL值 会 自 动 减 1, 当 TTL=0时 , 会 引 起 “ 超 时 ” 错 误 )。 开始 时 , 设 定 TTL等 于 1, 也 就 是 说 , 一 旦 它 抵 达 路 途 中 的 第一 个 路 由 器 , TTL首 先 会 超 时 (变 成 0), 这 样 便 会 造 成 路 由 器生 成 一 个 ICMP“超 时 ” 数 据 包 (该 包 含 有 产 生 “ 超 时 ” 路 由 器的 地 址 信 息 ); 随 后 , 最 初 的 TTL值 递 增 1, 以 便 UDP包 能 继续 传 到 下 一 个 路 由 器 , 而 生 成 的 ICMP超 时 包 会 自 下 一 个 路由 器 返 回 , 只 需 将 返 回 的 每 一 条 ICMP消 息 都 收 集 下 来 , 便能 为 中 途 经 过 的 路 由 器 IP地 址 勾 勒 出 一 个 清 晰 的 轮 廓 , 直 到最 终 的 目 标 主 机 。 125 之 所 以 认 为 tracert是 一 个 有 用 的 工 具 , 是 由 于 它 为 我 们提 供 了 大 量 的 与 途 中 所 经 历 的 路 由 器 有 关 的 信 息 。 对 具 体 的应 用 程 序 来 说 , 尽 管 需 要 执 行 tracert的 机 会 比 ping少 得 多 ,但 对 某 些 特 定 的 任 务 而 言 , 只 有 tracert才 能 执 行 它 们 。 实 现tracert程 序 时 , 只 需 将 ICMP数 据 包 简 单 地 发 给 目 的 地 , 同 时连 续 递 增 更 改 TTL的 值 即 可 。 当 TTL“超 时 ” 的 话 , 这 样 做 也可 能 会 造 成 一 条 ICMP错 误 消 息 的 返 回 。 注 意 , 这 种 方 法 和ping有 着 某 些 共 同 之 处 , 它 也 只 要 求 使 用 一 个 套 接 字 (安 装ICMP协 议 )。 126 2 tracert程 序 设 计 由 以 上 程 序 原 理 可 知 , tracert程 序 实 现 的 关 键 在 于 TTL值 的 设 置 。 SetTTL()函 数 可 完 成 该 功 能 。 BOOL SetTTL(SOCKET s, int nValue) int ret = :setsockopt(s, IPPROTO_IP, IP_TTL, (char*) return ret != SOCKET_ERROR; 利 用 SetTTL()函 数 , 将 ping程 序 的 for循 环 替 换 为 下 面 部分 即 可 , 就 可 以 实 现 tracert程 序 。 127 int main() ttl = 1; do int nRet; int notdone = 1; SetTTL(s, ttl); pIcmp-icmp_checksum = 0; 128 pIcmp-icmp_timestamp = GetTickCount(); pIcmp-icmp_sequence = nSeq+; pIcmp-icmp_checksum = checksum(USHORT*)buff, sizeof(ICMP_HDR) + 32); /发 送 ICMP回 应 请 求 nRet = sendto(sRaw,buff, sizeof(ICMP_HDR)+32, 0, (SOCKADDR *) if (nRet = SOCKET_ERROR) 129 printf(sendto failed: %dn, WSAGetLastError(); return -1; /接 收 并 解 析 ICMP封 包 , 过 滤 ICMP数 据 包 的 类 型 为 3、11, 代 码 为 3的 响 应 包 nRet = recvfrom(sRaw, recvBuf, 1024, 0, (sockaddr*) if(nRet = SOCKET_ERROR) if(WSAGetLastError() = WSAETIMEDOUT) 130 printf( timed outn); continue; printf( recvfrom() failed: %dn, :WSAGetLastError(); return -1; 131 if(pICMPHdr-icmp_type!=11 time=GetTickCount(); ICMP_HDR* pRecvIcmp = (ICMP_HDR*)(recvBuf + 20); 132 time = time - pRecvIcmp-icmp_timestamp; char *soucIP = :inet_ntoa(recvAddr.sin_addr); printf(echo form %s ;ttl is %d; delay is %d ms n, soucIP ,ttl, time); /检 查 响 应 是 否 来 自 于 目 的 地 址 notdone= memcmp( ttl+;/ttl值 累 加 while (notdone) 上 述 程 序 假 设 网 络 为 IPv4网 络 , 通 信 状 态 良 好 且 无 其 他干 扰 。 134 libnet是 专 门 用 来 构 造 网 络 数 据 包 的 第 三 方 工 具 , 在 数据 包 构 造 效 率 方 面 要 优 于 Winpcap和 原 始 套 接 字 。7.4 基 于 libnet的 网 络 编 程 135 7.4.1 libnet工 作 原 理 libnet设 计 小 巧 而 有 效 , 易 于 使 用 。 libnet的 出 现 主 要 基于 以 下 两 个 原 因 : 一 是 为 网 络 程 序 员 提 供 一 个 简 单 的 编 程 接口 , 使 程 序 员 能 把 主 要 精 力 集 中 用 来 解 决 问 题 , 而 不 用 考 虑底 层 网 络 细 节 ; 二 是 libnet是 一 个 与 libpcap类 似 的 数 据 包 注 入器 , 可 以 直 接 用 来 编 写 有 关 网 络 测 试 、 网 络 故 障 诊 断 和 网 络安 全 等 方 面 的 应 用 程 序 和 工 具 的 强 大 开 发 包 , 并 提 供 许 多 扩展 功 能 。 许 多 网 络 工 具 (如 snort、 nmap)都 利 用 它 来 实 现 其 部分 功 能 。 虽 然 libpcap同 样 具 有 数 据 包 构 造 和 发 送 能 力 , 但 在构 造 数 据 包 方 面 没 有 libnet使 用 方 便 。 136 libnet的 主 要 目 的 是 用 来 构 造 和 注 入 网 络 数 据 包 , 而 不 是 捕获 网 络 数 据 包 。 通 过 与 libpcap配 合 使 用 (如 图 7-5所 示 ), libnet可 以 用 来 构 造 许 多 有 用 的 网 络 程 序 和 网 络 工 具 。 137 图 7-5 libnet与 libpcap的 关 系 138 libnet已 经 能 够 很 好 地 支 持 Windows了 。 以 libnet 1.1.2.1版 为 例 , 它 可 以 在 http:/linux. 载 到 , 另 外 , 安 装 该 版 本 的 Libnet还 需 预 先 安装 Winpcap 4.0.2(http:/www.winpcap.org/install/default.htm)和Winpcap Developer Pack 4.0.2(http:/www.winpcap.org/devel.htm)。 139 7.4.2 libnet的 使 用 方 法 1 libnet的 安 装 在 使 用 libnet之 前 要 先 对 其 进 行 安 装 。 由 于 下 载 的 是libnet源 码 , 因 此 要 对 源 码 进 行 编 译 才 能 够 使 用 。 具 体 安 装步 骤 如 下 : (1) 首 先 , 解 压 libnet数 据 压 缩 包 , 然 后 打 开 libnet中 的Win32文 件 夹 , 双 击 “ libnet.dsw”项 , 用 VC+6.0打 开 该 工 程 。 (2) 按 照 前 面 介 绍 的 方 法 将 advapi32.lib引 入 工 程 。 将Winpcap开 发 包 中 include文 件 夹 下 的 所 有 头 文 件 拷 入 Visual C+6.0 安 装 目 录 中 的 “ Include”文 件 夹 (或 在ToolsOptionsDirectories下 设 置 该 目 录 )。 140 (3) 安 装 PSDK, 在 ToolsOptionsDirectories下 设 置PSDK安 装 的 include与 lib目 录 。 (4) 编 译 libnet, 如 果 编 译 成 功 , 则 在 Win32目 录 下 会 生成 一 个 Debug目 录 , 里 面 就 有 刚 刚 编 译 生 成 的 libnet.lib和libnet.dll, 其 中 libnet.lib是 程 序 开 发 时 用 的 , libnet.dll是 运 行时 用 的 (注 意 , 是 “ 编 译 ” 而 不 是 “ 执 行 ” )。 编 译 的 过 程 中编 译 器 可 能 提 示 很 多 个 “ 警 告 ” , 可 以 不 去 理 会 。 将libnet.dll拷 贝 到 C:windowssystem32下 面 , 在 后 续 的 libnet程序 运 行 时 , 系 统 将 自 动 加 载 。 libnet.lib和 libnet.dll中 提 供 了 附录 5中 libnet的 函 数 。 141 2 libnet的 使 用 步 骤 libnet提 供 了 两 种 接 口 , 一 种 是 在 IP层 构 造 数 据 包 , 另 一种 是 在 链 路 层 构 造 数 据 包 , 可 以 选 择 其 中 一 种 作 为 注 入 数 据包 的 入 口 。 链 路 层 接 口 在 数 据 链 路 层 构 造 数 据 包 (链 路 层 帧 ),而 IP层 接 口 在 网 络 层 构 造 数 据 包 (IP包 )。 链 路 层 接 口 的 功 能虽 更 为 强 大 , 但 程 序 也 比 较 复 杂 , 编 码 更 多 , 如 果 要 构 造ARP/RARP/以 太 网 帧 , 则 只 能 采 用 链 路 层 接 口 。 IP层 接 口 相对 要 简 单 一 些 (两 种 接 口 的 比 较 见 图 7-6)。 142 图 7-6 IP层 接 口 与 链 路 层 接 口 比 较 143 表 7-2 IP层 接 口 与 链 路 层 接 口 函 数 集 144 要 构 造 数 据 包 并 发 送 到 网 络 中 , 一 个 标 准 的 处 理 过 程 通常 包 括 以 下 六 个 步 骤 : 初 始 化 存 储 空 间 ; 初 始 化 网 络 ; 构 造 数 据 包 ; 计 算 数 据 包 的 校 验 和 ; 把 数 据 包 的 发送 到 网 络 中 ; 关 闭 网 络 接 口 , 释 放 内 存 。 下 面 对 上 述 各 步 进 行 具 体 介 绍 。 (1) 存 储 空 间 分 配 和 初 始 化 。 在 应 用 程 序 中 使 用 libnet的第 一 个 步 骤 就 是 为 数 据 包 分 配 存 储 空 间 , 通 常 采 用 调 用libnet_init_packet()函 数 的 方 法 来 完 成 。 程 序 员 事 先 必 须 知 道将 要 构 造 数 据 包 的 大 小 。 145 如 果 准 备 构 造 一 个 简 单 的 TCP数 据 包 , 包 中 带 有 30个 字 节 的负 载 (payload), 网 络 层 采 用 IP层 接 口 , 那 么 , 则 需 要 为 这 个数 据 包 分 配 70个 字 节 (IP header +TCP header + payload)的 存储 空 间 。 如 果 要 构 造 一 个 同 样 的 数 据 包 , 而 采 用 libnet的 链路 层 接 口 , 则 需 要 84个 字 节 (Ethernet header + IP header + TCP header + payload)的 存 储 空 间 。 为 了 安 全 起 见 , 程 序 员可 以 分 配 IP_MAXPACKET + ETH_H字 节 (65549)的 存 储 空间 , 以 满 足 绝 大 部 分 应 用 的 需 要 。 程 序 结 束 前 , 要 调 用 函 数libnet_destroy_packet()释 放 已 分 配 的 存 储 空 间 。 146 分 配 存 储 空 间 的 另 一 种 方 法 是 通 过 arena接 口 。 arena是一 个 可 以 一 次 分 配 多 块 存 储 空 间 的 缓 存 池 。 libnet的 arena接口 在 需 要 为 不 同 大 小 数 据 包 分 配 存 储 空 间 时 非 常 有 用 。 通 过函 数 libnet_init_packet

注意事项

本文(通信网络程序设计(王晓东西电版)第7章直接网络编程)为本站会员(xiao****017)主动上传,装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知装配图网(点击联系客服),我们立即给予删除!

温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!