当前位置:文档之家 > 网络课设-ICMP

网络课设-ICMP

计算机网络课程设计

ICMP协议

专业名称计算机科学与技术班级学号

学生姓名

指导教师

设计时间2011.7.4~2010.7.17

课程设计任务书

专业:计算机科学与技术学号:学生姓名:

设计题目:ICMP协议

一、设计实验条件

综合楼808实验室

二、设计任务及要求

1.利用VB实现ICMP的基本功能;

2.ICMP的Ping排错工具;

3.ICMP的Traceroute排错工具。

三、设计报告的内容

1.设计题目与设计任务

设计题目:ICMP协议

设计任务:利用VB实现ICMP的基本功能

2.前言

ICMP(Internet Control Message Protocol)是网际控制报文协议。它是TCP/IP 协议族的一个子协议,属于网络层协议。主要用于在主机与路由器之间传递控制信息,提供差错报告和网络诊断的功能,例如目的主机不可达,发送分组超时等消息。当遇到IP数据无法访问目标、IP路由器无法按当前的传输速率转发数据包等情况时,会自动发送ICMP消息。

从技术角度来说,ICMP就是一个“错误侦测与回报机制”。常用的ICMP 工具有Ping和Traceroute两个。Ping用来检测远端主机是否可达,诊断网络连通情况。Traceroute用来发现到目的节点所经历的所有路由器,获得网络的拓扑结构信息,诊断排除网络故障。

本课程设计中实现了使用ICMP进行排错的工具:Ping和Traceroute。

3.设计主体(各部分设计内容、分析、结论等)

1)关于ICMP报文

ICMP报文可划分为两大类:差错报告报文(error-reporting messages)和查询报文(query messages)。差错报告报文报告了路由器或主机(终点)在处理IP数据报时可能遇到的问题。查询报文总是成双成对地出现,它帮助主机或网络管理员从某个路由器或对方主机那里获取特定的信息。例如,结点可以去发现它们的邻站。同样,主机也可以发现和了解它们所在的网络上的一些路由器的情况,而路由器又能够帮助一个结点改变报文的路由。表1列出了每一类ICMP报文。

表1. ICMP报文

种类类型报文

差错报告报文 3 终点不可达

4 源点抑制

11 超时

12 参数问题

5 改变路由

查询报文8或0 回送请求或回答

13或14 时间戳请求或回答

报文格式:

ICMP报文由一个8字节的首部和可变长度的数据部分组成。虽然对每一种报文类型,首部的一般格式都是不同的,但前4个字节对所有类型来说都是相同的。如图1所示,第一个字段是ICMP的类型,它定义了报文类型。代码字段指明了发送这个特定报文类型的原因。最后一个共同的字段是检验和字段。其余部分对于每一种类型的报文都是特有的。

在差错报文中,数据部分携带的是用于找出引起差错的原始分组的信息。在查询报文中,数据部分携带的是基于查询类型的额外信息。

下图中,图1给出了ICMP报文的一般格式,图2给出了ICMP报文的类型。

8位8位16位类型代码校验和

首部的其余部分

数据部分

图1:ICMP报文的一般格式

网络课设-ICMP

图2:ICMP报文类型

2)关于Ping

Ping程序可以查出某个主机是否已加电并能够响应。

源主机发送ICMP回送请求报文(类型:8,代码:0)。如果终点已加电,就会返回ICMP回送回答报文。程序ping在回送请求和回送回答报文中设置了标识符字段,并使序号从0开始,每发送一个新报文序号就递增1。Ping能够计算往返时间,它在报文的数据部分插入了发送时间。当分组到达时,它就用到达时间减去出发时间得出往返时间(round-trip time, RTT)。

Ping程序结束后会发给我们一个统计值,这个统计值告诉我们发送的分组数、接受到的分组数、总时间、RTT的最小值、最大值和平均值。

3)关于Traceroute

Traceroute可以用来跟踪一个分组从源点到终点的路径。

这个程序很巧妙地使用了两个ICMP报文—超时报文和终点不可达报文来找出一个分组的路由。这是一个应用级程序,它使用UDP服务。

该诊断实用程序通过向目的地发送具有不同生存时间(TTL) 的ICMP回应报文,以确定至目的地的路由。路径上的每个路由器都要在转发该ICMP 回应报文之前将其TTL 值至少减1,因此TTL 是有效的跳转计数。当报文的TTL 值减少到0 时,路由器向源系统发回ICMP 超时信息。通过发送TTL 为 1 的第一个回应报文并且在随后的发送中每次将TTL 值加1,直到目标响应或达到最大TTL 值,Traceroute 可以确定路由。通过检查中间路由器发发回的ICMP 超时(time Exceeded) 信息,可以确定路由器。

Traceroute程序记录了到达的IP数据报的目的地址,跟踪了从源点到终点的路径,并记下了往返时间。

4)程序关键代码

声明Windows API函数:

Declare Function gethostname Lib "wsock32.dll" (ByVal hostname$, HostLen&) As Long

Declare Function gethostbyname& Lib "wsock32.dll" (ByVal hostname$)

Declare Function WSAGetLastError Lib "wsock32.dll" () As Long

Declare Function WSAStartup Lib "wsock32.dll" (ByVal wVersionRequired&, lpWSAData As WSAdata) As Long

Declare Function WSACleanup Lib "wsock32.dll" () As Long

Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)

Declare Function IcmpCreateFile Lib "icmp.dll" () As Long

Declare Function IcmpCloseHandle Lib "icmp.dll" (ByVal HANDLE As Long) As Boolean

Declare Function IcmpSendEcho Lib "ICMP" (ByVal IcmpHandle As Long, ByVal DestAddress As Long, _

ByVal RequestData As String, ByVal RequestSize As Integer, RequestOptns As IP_OPTION_INFORMATION, _

ReplyBuffer As IP_ECHO_REPL Y, ByVal ReplySize As Long, ByVal TimeOut As Long) As Boolean

Form中的代码

显示:

If TraceRT = False Then

If pIPe.Status = 0 Then

Text3.Text = Text3.Text + " Reply from " + RespondingHost + ": Bytes = " + Trim$(CStr(pIPe.DataSize)) + " RTT = " + Trim$(CStr(pIPe.RoundTripTime)) + "ms TTL = " + Trim$(CStr(pIPe.Options.TTL)) + Chr$(13) + Chr$(10)

Else

Text3.Text = Text3.Text + " Reply from " + RespondingHost + ": " + RCode + Chr$(13) + Chr$(10)

End If

Else

If TTL - 1 < 10 Then Text3.Text = Text3.Text + " Hop # 0" + CStr(TTL - 1) Else Text3.Text = Text3.Text + " Hop # " + CStr(TTL - 1)

Text3.Text = Text3.Text + " " + RespondingHost + Chr$(13) + Chr$(10) End If

Socket:

MaxSockets = WSAdata.iMaxSockets

If MaxSockets < 0 Then

MaxSockets = 65536 + MaxSockets

End If

MaxUDP = WSAdata.iMaxUdpDg

If MaxUDP < 0 Then

MaxUDP = 65536 + MaxUDP

End If

Ping:

vbWSAStartup ' Initialize Winsock

vbGetHostByName ' Get the IPAddress for the Host vbIcmpCreateFile ' Get ICMP Handle

vbIcmpSendEcho ' Send the ICMP Echo Request

vbIcmpCloseHandle ' Close the ICMP Handle vbWSACleanup ' Close Winsock

Trace:

vbWSAStartup ' Initialize Winsock vbGetHostByName ' Get the IPAddress for the Host vbIcmpCreateFile ' Get ICMP Handle vbIcmpSendEcho ' Send the ICMP Echo Request vbIcmpCloseHandle ' Close the ICMP Handle vbWSACleanup ' Close Winsock

5)程序运行截图

网络课设-ICMP

图3 ping

网络课设-ICMP

图4 Traceroute

4.结束语

本课程设计实现了使用ICMP进行排错的工具:Ping和Traceroute。由于是第一次进行网络编程,在设计的过程中遇到了很多问题,在编写代码的时候常常出错,经过同学的指教,才有了现在程序的正常运行。在课程设计的过程中我遇到了很多麻烦,有些问题弄得我焦头烂额,但从中我也体会到了编写程序的过程是很辛苦的,同时也是快乐的。每一次难题的解决,心里都有说不出的高兴。

系统基本完成后,又要多次试用和完善它。程序的编写能力靠不断地积累,同时,多借鉴高手们的编程方法,不失为一种快速提高编程能力的途径。

5.参考资料

[1] Behrouz A.Forouzan.TCP/IP协议族[M] .北京:清华大学出版社,2011.

[2] W.Richard Stevens.TCP/IP详解[M] .北京:机械工业出版社,2008.

[3] 刘彬彬,高春燕,孙秀梅.Visual Basic从入门到精通[M] .北京:清华大学出版社,2008.

[4] 尚展垒,包空军,陈嫄玲.Visual Basic 2008程序设计技术[M] .北京:清华大学出版社,2011.

四、设计时间与安排

1、设计时间:2周

2、设计时间安排:2010.7.5~2010.7.16

熟悉实验设备、收集资料:5 天

设计图纸、实验、计算、程序编写调试: 4 天

编写课程设计报告: 2 天

答辩:1 天

附录:

模块ICMP:

' WSock32 UDTs

Type Inet_address

Byte4 As String * 1

Byte3 As String * 1

Byte2 As String * 1

Byte1 As String * 1

End Type

Public IPLong As Inet_address

Type WSAdata

wVersion As Integer

wHighVersion As Integer

szDescription(0 To 255) As Byte

szSystemStatus(0 To 128) As Byte

iMaxSockets As Integer

iMaxUdpDg As Integer

lpVendorInfo As Long

End Type

Type Hostent

h_name As Long

h_aliases As Long

h_addrtype As Integer

h_length As Integer

h_addr_list As Long

End Type

Type IP_OPTION_INFORMATION

TTL As Byte ' Time to Live (used for traceroute) Tos As Byte ' Type of Service (usually 0)

Flags As Byte ' IP header Flags (usually 0)

OptionsSize As Long ' Size of Options data (usually 0, max 40)

OptionsData As String * 128 ' Options data buffer

End Type

Public pIPo As IP_OPTION_INFORMA TION

Type IP_ECHO_REPL Y

Address(0 To 3) As Byte ' Replying Address

Status As Long ' Reply Status

RoundTripTime As Long ' Round Trip Time in milliseconds

DataSize As Integer ' reply data size

Reserved As Integer ' for system use

data As Long ' pointer to echo data

Options As IP_OPTION_INFORMA TION ' Reply Options

End Type

Public pIPe As IP_ECHO_REPL Y

' WSock32 Subroutines and Functions

Declare Function gethostname Lib "wsock32.dll" (ByVal hostname$, HostLen&) As Long Declare Function gethostbyname& Lib "wsock32.dll" (ByVal hostname$)

Declare Function WSAGetLastError Lib "wsock32.dll" () As Long

Declare Function WSAStartup Lib "wsock32.dll" (ByVal wVersionRequired&, lpWSAData As WSAdata) As Long

Declare Function WSACleanup Lib "wsock32.dll" () As Long

' Kernel32 Subroutines and Functions

Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)

' ICMP Subroutines and Functions

' IcmpCreateFile will return a file handle

Declare Function IcmpCreateFile Lib "icmp.dll" () As Long

' The IcmpCreateFile function returns an open handle on success. On failure, the function returns INV ALID_HANDLE_V ALUE. Call the GetLastError function for extended error

information.

' Pass the handle value from IcmpCreateFile to the IcmpCloseHandle. It will return

' a boolean value indicating whether or not it closed successfully.

Declare Function IcmpCloseHandle Lib "icmp.dll" (ByVal HANDLE As Long) As Boolean ' If the handle is closed successfully the return value is TRUE, otherwise FALSE. Call the GetLastError function for extended error information.

' IcmpHandle returned from IcmpCreateFile

' DestAddress is a pointer to the first entry in the hostent.h_addr_list

' RequestData is a null-terminated 64-byte string filled with ASCII 170 characters

' RequestSize is 64-bytes

' RequestOptions is a NULL at this time

' ReplyBuffer

' ReplySize

' Timeout is the timeout in milliseconds

Declare Function IcmpSendEcho Lib "ICMP" (ByVal IcmpHandle As Long, ByVal DestAddress As Long, _

ByVal RequestData As String, ByVal RequestSize As Integer, RequestOptns As

IP_OPTION_INFORMA TION, _

ReplyBuffer As IP_ECHO_REPL Y, ByVal ReplySize As Long, ByVal TimeOut As Long) As Boolean

' 可以通过发送echo包知道当前的连接节点有那些路径

Form1代码:

' WSock32 Variables

Dim iReturn As Long, sLowByte As String, sHighByte As String

Dim sMsg As String, HostLen As Long, Host As String

Dim Hostent As Hostent, PointerToPointer As Long, ListAddress As Long

Dim WSAdata As WSAdata, DotA As Long, DotAddr As String, ListAddr As Long

Dim MaxUDP As Long, MaxSockets As Long, i As Integer

Dim Description As String, Status As String

' ICMP Variables

Dim bReturn As Boolean, hIP As Long

Dim szBuffer As String

Dim Addr As Long

Dim RCode As String

Dim RespondingHost As String

' TRACERT Variables

Dim TraceRT As Boolean

Dim TTL As Integer

' WSock32 Constants

Const WS_VERSION_MAJOR = &H101 \ &H100 And &HFF&

Const WS_VERSION_MINOR = &H101 And &HFF&

Const MIN_SOCKETS_REQD = 0

Sub GetRCode()

If pIPe.Status = 0 Then RCode = "Success"

If pIPe.Status = 11001 Then RCode = "Buffer too Small"

If pIPe.Status = 11002 Then RCode = "Dest Network Not Reachable"

If pIPe.Status = 11003 Then RCode = "Dest Host Not Reachable"

If pIPe.Status = 11004 Then RCode = "Dest Protocol Not Reachable"

If pIPe.Status = 11005 Then RCode = "Dest Port Not Reachable"

If pIPe.Status = 11006 Then RCode = "No Resources Available"

If pIPe.Status = 11007 Then RCode = "Bad Option"

If pIPe.Status = 11008 Then RCode = "Hardware Error"

If pIPe.Status = 11009 Then RCode = "Packet too Big"

If pIPe.Status = 11010 Then RCode = "Rqst Timed Out"

If pIPe.Status = 11011 Then RCode = "Bad Request"

If pIPe.Status = 11012 Then RCode = "Bad Route"

If pIPe.Status = 11013 Then RCode = "TTL Exprd in Transit"

If pIPe.Status = 11014 Then RCode = "TTL Exprd Reassemb"

If pIPe.Status = 11015 Then RCode = "Parameter Problem"

If pIPe.Status = 11016 Then RCode = "Source Quench"

If pIPe.Status = 11017 Then RCode = "Option too Big"

If pIPe.Status = 11018 Then RCode = " Bad Destination"

If pIPe.Status = 11019 Then RCode = "Address Deleted"

If pIPe.Status = 11020 Then RCode = "Spec MTU Change"

If pIPe.Status = 11021 Then RCode = "MTU Change"

If pIPe.Status = 11022 Then RCode = "Unload"

If pIPe.Status = 11050 Then RCode = "General Failure"

RCode = RCode + " (" + CStr(pIPe.Status) + ")"

DoEvents

If TraceRT = False Then

If pIPe.Status = 0 Then

Text3.Text = Text3.Text + " Reply from " + RespondingHost + ": Bytes = " + Trim$(CStr(pIPe.DataSize)) + " RTT = " + Trim$(CStr(pIPe.RoundTripTime)) + "ms TTL = " + Trim$(CStr(pIPe.Options.TTL)) + Chr$(13) + Chr$(10)

Else

Text3.Text = Text3.Text + " Reply from " + RespondingHost + ": " + RCode + Chr$(13) + Chr$(10)

End If

Else

If TTL - 1 < 10 Then Text3.Text = Text3.Text + " Hop # 0" + CStr(TTL - 1) Else Text3.Text = Text3.Text + " Hop # " + CStr(TTL - 1)

Text3.Text = Text3.Text + " " + RespondingHost + Chr$(13) + Chr$(10) End If

End Sub

Sub vbGetHostByName()

Dim szString As String

Host = Trim$(Text1.Text) ' Set Variable Host to Value in Text1.text

szString = String(64, &H0)

Host = Host + Right$(szString, 64 - Len(Host))

If gethostbyname(Host) = SOCKET_ERROR Then ' If WSock32 error, then tell me about it

sMsg = "Winsock Error" & Str$(WSAGetLastError())

MsgBox sMsg, vbOKOnly, "VB4032-ICMPEcho"

Else

PointerToPointer = gethostbyname(Host) ' Get the pointer to the address of the winsock hostent structure

CopyMemory Hostent.h_name, ByVal _

PointerToPointer, Len(Hostent) ' Copy Winsock structure to the VisualBasic structure

ListAddress = Hostent.h_addr_list ' Get the ListAddress of the Address List

CopyMemory ListAddr, ByVal ListAddress, 4 ' Copy Winsock structure to the VisualBasic structure

CopyMemory IPLong, ByVal ListAddr, 4 ' Get the first list entry from the Address List

CopyMemory Addr, ByVal ListAddr, 4

Label3.Caption = Trim$(CStr(Asc(IPLong.Byte4)) + "." + CStr(Asc(IPLong.Byte3)) _ + "." + CStr(Asc(IPLong.Byte2)) + "." + CStr(Asc(IPLong.Byte1))) End If

End Sub

Sub CenterForm()

Form1.Left = (Screen.Width - Form1.ScaleWidth) \ 2

Form1.Top = (Screen.Height - Form1.ScaleHeight) \ 2

End Sub

Sub vbGetHostName()

Host = String(64, &H0) ' Set Host value to a bunch of spaces

If gethostname(Host, HostLen) = SOCKET_ERROR Then ' This routine is where we get the host's name

sMsg = "WSock32 Error" & Str$(WSAGetLastError()) ' If WSOCK32 error, then tell me

about it

MsgBox sMsg, vbOKOnly, "VB4032-ICMPEcho"

Else

Host = Left$(Trim$(Host), Len(Trim$(Host)) - 1) ' Trim up the results

Text1.Text = Host ' Display the host's name in label1

End If

End Sub

Sub vbIcmpSendEcho()

Dim NbrOfPkts As Integer

szBuffer = "abcdefghijklmnopqrstuvwabcdefghijklmnopqrstuvwabcdefghijklmnopqrstuvwabcdefghijklmnopqrs tuvwabcdefghijklmnopqrstuvwabcdefghijklm"

If IsNumeric(Text5.Text) Then

If Val(Text5.Text) < 32 Then Text5.Text = "32"

If Val(Text5.Text) > 128 Then Text5.Text = "128"

Else

Text5.Text = "32"

End If

szBuffer = Left$(szBuffer, Val(Text5.Text))

If IsNumeric(Text4.Text) Then

If Val(Text4.Text) < 1 Then Text4.Text = "1"

Else

Text4.Text = "1"

End If

If TraceRT = True Then Text4.Text = "1"

For NbrOfPkts = 1 To Trim$(Text4.Text)

DoEvents

bReturn = IcmpSendEcho(hIP, Addr, szBuffer, Len(szBuffer), pIPo, pIPe, Len(pIPe) + 8, 2700)

If bReturn Then

RespondingHost = CStr(pIPe.Address(0)) + "." + CStr(pIPe.Address(1)) + "." + CStr(pIPe.Address(2)) + "." + CStr(pIPe.Address(3))

GetRCode

Else ' I hate it when this happens. If I get an ICMP timeout

' during a TRACERT, try again.

If TraceRT Then

TTL = TTL - 1

Else ' Don't worry about trying again on a PING, just timeout

Text3.Text = Text3.Text + "ICMP Request Timeout" + Chr$(13) + Chr$(10) End If

End If

Next NbrOfPkts

End Sub

Sub vbWSAStartup()

' Subroutine to Initialize WSock32

iReturn = WSAStartup(&H101, WSAdata)

If iReturn <> 0 Then ' If WSock32 error, then tell me about it

MsgBox "WSock32.dll is not responding!", vbOKOnly, "VB4032-ICMPEcho"

End If

If LoByte(WSAdata.wVersion) < WS_VERSION_MAJOR Or (LoByte(WSAdata.wVersion) = WS_VERSION_MAJOR And HiByte(WSAdata.wVersion) < WS_VERSION_MINOR) Then sHighByte = Trim$(Str$(HiByte(WSAdata.wV ersion)))

sLowByte = Trim$(Str$(LoByte(WSAdata.wVersion)))

sMsg = "WinSock Version " & sLowByte & "." & sHighByte

sMsg = sMsg & " is not supported "

MsgBox sMsg, vbOKOnly, "VB4032-ICMPEcho"

End

End If

If WSAdata.iMaxSockets < MIN_SOCKETS_REQD Then

sMsg = "This application requires a minimum of "

sMsg = sMsg & Trim$(Str$(MIN_SOCKETS_REQD)) & " supported sockets."

MsgBox sMsg, vbOKOnly, "VB4032-ICMPEcho"

End

End If

MaxSockets = WSAdata.iMaxSockets

' WSAdata.iMaxSockets is an unsigned short, so we have to convert it to a signed long If MaxSockets < 0 Then

MaxSockets = 65536 + MaxSockets

End If

MaxUDP = WSAdata.iMaxUdpDg

If MaxUDP < 0 Then

MaxUDP = 65536 + MaxUDP

End If

' Process the Winsock Description information

Description = ""

For i = 0 To WSADESCRIPTION_LEN

If WSAdata.szDescription(i) = 0 Then Exit For

Description = Description + Chr$(WSAdata.szDescription(i))

Next i

' Process the Winsock Status information

Status = ""

For i = 0 To WSASYS_STA TUS_LEN

If WSAdata.szSystemStatus(i) = 0 Then Exit For

Status = Status + Chr$(WSAdata.szSystemStatus(i))

Next i

End Sub

Function HiByte(ByVal wParam As Integer)

HiByte = wParam \ &H100 And &HFF&

End Function

Function LoByte(ByVal wParam As Integer)

LoByte = wParam And &HFF&

End Function

Sub vbWSACleanup()

' Subroutine to perform WSACleanup

iReturn = WSACleanup()

If iReturn <> 0 Then ' If WSock32 error, then tell me about it.

sMsg = "WSock32 Error - " & Trim$(Str$(iReturn)) & " occurred in Cleanup"

MsgBox sMsg, vbOKOnly, "VB4032-ICMPEcho"

End

End If

End Sub

Sub vbIcmpCloseHandle()

bReturn = IcmpCloseHandle(hIP)

If bReturn = False Then

MsgBox "ICMP Closed with Error", vbOKOnly, "VB4032-ICMPEcho"

End If

End Sub

Sub vbIcmpCreateFile()

hIP = IcmpCreateFile()

If hIP = 0 Then

MsgBox "Unable to Create File Handle", vbOKOnly, "VBPing32"

End If

End Sub

Private Sub Command1_Click()

vbWSAStartup ' Initialize Winsock

If Len(Text1.Text) = 0 Then

vbGetHostName

End If

If Text1.Text = "" Then

MsgBox "No Hostname Specified!", vbOKOnly, "VB4032-ICMPEcho" ' Complain if No Host Name Identified

vbWSACleanup

Exit Sub

End If

vbGetHostByName ' Get the IPAddress for the Host

vbIcmpCreateFile ' Get ICMP Handle

' The following determines the TTL of the ICMPEcho

If IsNumeric(Text2.Text) Then

If (Val(Text2.Text) > 255) Then Text2.Text = "255"

If (Val(Text2.Text) < 2) Then Text2.Text = "2"

Else

Text2.Text = "255"

End If

pIPo.TTL = Trim$(Text2.Text)

vbIcmpSendEcho ' Send the ICMP Echo Request

vbIcmpCloseHandle ' Close the ICMP Handle

vbWSACleanup ' Close Winsock

End Sub

Private Sub Command2_Click()

Text3.Text = ""

End Sub

Private Sub Command3_Click()

Text3.Text = ""

vbWSAStartup ' Initialize Winsock

If Len(Text1.Text) = 0 Then

vbGetHostName

End If

If Text1.Text = "" Then

MsgBox "No Hostname Specified!", vbOKOnly, "VB4032-ICMPEcho" ' Complain if