计算机网络工程课程设计报告
题 目: Ping程序实现
学生姓名:
学 号:
专业班级: 计科专业班
组姓名
指导教师:
设计时间: 2013年学期第X周
指导老师意见:
评定成绩: 签名:
日期: 年 月 日
目录
课程设计目意义 2
二课程设计容求 2
1容: 2
2求: 2
三课程设计相关技术 2
四课程设计程 2
1Ping模块 2
2功控制模块 4
3数报解析模块 5
五课程设计结 6
六参考文献 7
七附 录(程序清单) 7
八心体会 11
课程设计目意义
利ICMP数包C语言实现Ping命令程序实现基Ping操作发送ICMP回显请求报文测试—机机间连通情况通程序训练学生熟悉ICMP报文结构学生ICMP更深理解掌握Ping程序设计方法掌握网络编程方法技巧编写出功更强程序
二课程设计容求
1容:
C语言实现Ping命令程序实现基Ping操作发送ICMP回显请求报文测试—机机间连通情况
2求:
1) 独立完成程序设计编码调试
2) 系统利C语言实现程序调试环境Turbo CVC
3) 课程设计规范书写课程设计报告
4) 采VC环境进行调试运行
三课程设计相关技术
Ping程序面户应程序该程序ICMP封装机制通IP协议工作实现直接IPICMP包进行操作实验中RAW模式socket编程首先定义IP数报首部IP数报基础定义ICMP数报首部初始化全局变量接着定义填充ICMP数报字段函数FillICMPData()校验函数checksum()解读ICMP报首部函数DecodeICMPHeader()释放资源函Cleanup()函数通调函数实现Ping命令功IP头ICMP头设置分参RFC791RFC792标准包含必信息程序设置main()函数函数库函数实现套接字编程数包发送接收中数包发送调sendto()数包接收调recvfrom( )发送数包时会遇阻塞者目标机通造成超时需发送数包调函数判断否超时处调库函数setsockopt()实现超时判断次校验函数采移位方法进行计算
套接字需文件头文件Winsocket2h库文件WS2_32LIB动态库W32_32DLL创建套接字时候参数创建套接字前必须首先WSAStartup函数
四课程设计程
1Ping模块
Ping()函数程序核心部分基调模块函数实现终功布骤包括:定义初始化全局变量开socket动态库设置接收发送超时值域名址解析分配存创建初始化ICMP报文发送ICMP请求报文接收ICMP 应答报文解读应答报文输出Ping结果释放占资源流程页图21示
注释:
(1) 该模块非处理包括判断输出判断结果含义
(2) 程序没运行次输出四行结果(前提输入址效)欲次PING址必须重新启动程序
(3) 输入时输入目标机名然ping结果TIMEOUT
开始
定义初始化全局变量
判断WSAStartup函数否调成功
输出调失败
否
创建套接字设置socket接收超时发送超时选项
输入PINGIP址
解析输入容设置PING参数
创建填充ICMP数报文
判断否已发送四次
Break
发送接收解析数包
输出PIING结果
结束
清残余
否
2功控制模块
功控制模块模块提供调函数该模块包括参数获取功计算ICMP数报文检验清SOCKETICMP包数接受缓区占资源释放功显示尸帮助功该模块包含三函数实现流程图22示
Checksum开始
定义初始化cksum
(size > 1)
确定cksumsize
if (size)
计算校验cksum获结果
cksum + *(UCHAR*)buffer
否
结束
Cleanup开始
if (m_hSocket INVALID_SOCKET)
关闭套接字
释放占资源
清ICMP包数接受缓区
F
WSACleanup()
结束
图22 功控制模块
注释:
aillICMPData系列初始化语句流程图中画出
bCleanup()函数中WSACleanup()HeapFree()closesocket()库函数checksum()校验函数冗余校验种形式 通错误检测方法空间(通信)者时间(计算机存储)传送数完整性进行检查种简单方法
3数报解析模块
数报解析模块提供解读IP选项解读IcMP报文功机收目机返回1cMP回显应答报文开始逐解读IcMP报文果需记录路情况IcMP解析函数调IP选项解读函数实现IP路输出(程序没功该模块DecodeICMPHeader函数实现中间会调模块相应函数流程图图23
注释:
a判断否数报回应前判断回应少容语句未呈现出
b函数GetTickCount()记录时机处现时间(毫秒级)
DecodeICMPHeader开始
定义相关变量初始化
tick GetTickCount()
回应报文
输出
tick0[icmpcount]tick icmphdr>timestamp
判断时间否1ms
printf(Reply from s dytesd time<1ms icmp_seq d\ninet_ntoa(from>sin_addr) bytes icmphdr>i_seq )
printf(Reply from s dytesd timed icmp_seq d\ninet_ntoa(from>sin_addr) bytestick0[icmpcount] icmphdr>i_seq)
icmpcount++
结束
结束
否
图23 数报解析模块
五课程设计结
1运行操作结果:vc里运行界面:
2输入机ip址:
3输入网ip结果:
4 网络连通时会出现图结果
六参考文献
1Visual C++网络通信编程实案例精选(第二版)曹衍龙 刘海英 编著
2Windows网络编程技术 (美)
七附 录(程序清单)
#pragma comment(libws2_32lib)
#include
#include
#include
#include
#include
typedef struct iphdr
{
unsigned int h_len4 头长度
unsigned int version4 IP版
unsigned char service 服务类型
unsigned short total_len 包总长度
unsigned short ident 包标示身份
unsigned short frag_and_flags 标志
unsigned char ttl 包生命周期
unsigned char proto 协议类型
unsigned short checksum IP 校验
unsigned int sourceIP 源IP
unsigned int destIP 目标IP
} IpHeader
#define ICMP_ECHO 8 ICMP报文类型回显请求
#define ICMP_ECHOREPLY 0 ICMP报文类型回显应答
#define ICMP_MIN 8 ICMP数报
typedef struct icmphdr
{
BYTE i_type ICMP报文类型
BYTE i_code 该类型中代码号
USHORT i_cksum 校验
USHORT i_id 惟标识符
USHORT i_seq 序列号
ULONG timestamp 时间戳
} IcmpHeader
#define DEF_PACKET_SIZE 32 默认数报
#define MAX_PACKET 1024 ICMP数报
#define MAX_IP_HDR_SIZE 60 IP头长度
初始化全局变量
int datasizeDEF_PACKET_SIZE
char *icmp_dataNULL
char *recvbufNULL
SOCKET m_hSocket INVALID_SOCKET
char *lpdestNULL
填充ICMP数报字段函数
void FillICMPData(char *icmp_data int datasize)
{
IcmpHeader *icmp_hdr NULL
char*datapart NULL
icmp_hdr (IcmpHeader*)icmp_data
icmp_hdr>i_type ICMP_ECHO
icmp_hdr>i_code 0
icmp_hdr>i_id (USHORT)GetCurrentProcessId()
icmp_hdr>i_cksum 0
icmp_hdr>i_seq 0
datapart icmp_data + sizeof(IcmpHeader)
}
校验函数
USHORT checksum(USHORT *buffer int size)
{ unsigned long cksum0
while (size > 1)
{ cksum + *buffer++ size sizeof(USHORT) }
if (size)
{ cksum + *(UCHAR*)buffer }
cksum (cksum >> 16) + (cksum & 0xffff)
cksum + (cksum >>16)return (USHORT)(~cksum)
}
解读ICMP报首部函数
void DecodeICMPHeader(char *buf int bytes SOCKADDR_IN *from)
{
IpHeader*iphdr NULL
IcmpHeader*icmphdr NULL
unsigned short iphdrlen
DWORD tick
static int icmpcount 0
iphdr (IpHeader *)buf
iphdrlen iphdr>h_len * 4
tick GetTickCount()
if (bytes < iphdrlen + ICMP_MIN)
{ printf(Too few bytes from s \r\ninet_ntoa(from>sin_addr)) }
icmphdr (IcmpHeader*)(buf + iphdrlen)
if (icmphdr>i_type ICMP_ECHOREPLY)
{ printf(nonecho type d received \r\n icmphdr>i_type) }
if (icmphdr>i_id (USHORT)GetCurrentProcessId())
{ printf(程序回应报文 \t错误代码 d\n WSAGetLastError()) }
DWORD tick0[4]
tick0[icmpcount]tick icmphdr>timestamp
if(tick0[icmpcount]<1)
printf(Reply from s bytesd time<1ms
icmp_seqd\ninet_ntoa(from>sin_addr) bytes icmphdr>i_seq )
else
printf(Reply from s bytesd timedms icmp_seq d\ninet_ntoa(from>sin_addr) bytestick0[icmpcount] icmphdr>i_seq)
icmpcount++
}
释放资源函数
void Cleanup()
{
if (m_hSocket INVALID_SOCKET)
closesocket(m_hSocket)
HeapFree(GetProcessHeap() 0 recvbuf)
HeapFree(GetProcessHeap() 0 icmp_data)
WSACleanup()
}
函数
void main()
{
WSADATA wsaData char a[100] printf(ping )
scanf(sa) lpdesta SOCKADDR_IN m_addrDest结构体
SOCKADDR_IN m_addrFrom int timeout1000 USHORT seq_no0
if (WSAStartup(MAKEWORD(2 2) &wsaData) 0)
{ printf(Sorry you cannot load socket dll) }
m_hSocket WSASocket (AF_INET SOCK_RAW IPPROTO_ICMP NULL 0WSA_FLAG_OVERLAPPED)创建原始套接字该套接字ICMP协议
if (m_hSocket INVALID_SOCKET) 果套接字创建成功
{ printf(socket 创建失败) }
int bread setsockopt(m_hSocket SOL_SOCKET SO_RCVTIMEO (char*)&timeout sizeof(timeout))设置接收超时值
if(bread SOCKET_ERROR)
{ printf(设置socket接收超时选项错误) }
timeout 1000
bread setsockopt(m_hSocket SOL_SOCKET SO_SNDTIMEO (char*)&timeout sizeof(timeout))设置发送超时值
if (bread SOCKET_ERROR)
{ printf(设置socket发送超时选项错误) }
memset(&m_addrDest 0 sizeof(m_addrDest)) 0初始化目址
m_addrDestsin_family AF_INET设置址族里表示IP址族
if ((m_addrDestsin_addrs_addr inet_addr(lpdest)) INADDR_NONE)址转化
{
struct hostent *hp NULL
if ((hp gethostbyname(lpdest)) NULL) 名字解析根机名获取IP址
{
memcpy(&(m_addrDestsin_addr) hp>h_addr hp>h_length)获取IP值赋目址中相应字段
m_addrDestsin_family hp>h_addrtype 获取址族值赋目址中相应字段
}
else
{
printf(找名 s 机\t错误代码 d\nlpdest exit(0)
} }
printf(Pinging s with 64 bytes of data \n\n inet_ntoa(m_addrDestsin_addr))
datasize + sizeof(IcmpHeader) 数报文需包含ICMP报头
根默认堆句柄堆中分配MAX_PACKET存块新分配存容初始化0
icmp_data(char*)HeapAlloc(GetProcessHeap()HEAP_ZERO_MEMORYMAX_PACKET)
recvbuf (char*) HeapAlloc(GetProcessHeap() HEAP_ZERO_MEMORYMAX_PACKET)
if (icmp_data) 果分配存成功
{ printf(堆分配错误) }
memset(icmp_data0MAX_PACKET)创建ICMP报文
FillICMPData(icmp_datadatasize)
开始发送接受ICMP包
int nCount0
while(1)
{ int bwrote
if(nCount++ 4)
break超指定记录条数退出
((IcmpHeader*)icmp_data)>i_cksum 0计算校验前校验字段设置0
((IcmpHeader*)icmp_data)>timestamp GetTickCount()获取操作系统启动现毫秒数设置时间戳
((IcmpHeader*)icmp_data)>i_seq seq_no++设置序列号
((IcmpHeader*)icmp_data)>i_cksum checksum((USHORT*)icmp_data datasize)计算校验
bwrote sendto(m_hSocket icmp_data datasize 0 (struct sockaddr*)&m_addrDest sizeof(m_addrDest))开始发送ICMP请求
if (bwrote SOCKET_ERROR)果发送成功
{
if (WSAGetLastError() WSAETIMEDOUT) 果超时成功
{ printf(Requrest timed out \r\n) continue }
printf(目标达\t错误代码 d\n WSAGetLastError())发送成功原
continue }
if (bwrote < datasize)
{ printf(Wrote d bytes \r\n bwrote) }
int fromlen sizeof(m_addrFrom)开始接收ICMP应答
breadrecvfrom(m_hSocketrecvbufMAX_PACKET0(struct sockaddr*)&m_addrFrom &fromlen)
if (bread SOCKET_ERROR)果接收成功
{
if (WSAGetLastError() WSAETIMEDOUT) 果超时成功
{ printf(Requrest timed out \r\n) continue } printf(接收数函数调错误\t错误代码 d\n WSAGetLastError())接收成功原
exit(0)
}
DecodeICMPHeader(recvbuf bread &m_addrFrom)解读接收ICMP数报
} Cleanup()
}
八心体会
次课程设计课题ping程序实现前实验课局域网中通路器交换机等设备
文档香网(httpswwwxiangdangnet)户传
《香当网》用户分享的内容,不代表《香当网》观点或立场,请自行判断内容的真实性和可靠性!
该内容是文档的文本内容,更好的格式请下载文档