1、C#使用Windows API時必須先使用DllImport來Include Library,主要使用下列15個網路相關的API:

      1-01、int WSAStartup(ushort wVersionrequested,ref WSDATA lpWSAData)

            一  使用Windows Socket必須成功的調用此函式,才可以完成其他一系列的初始化。

      1-02、int sock(int af,int type,int protocol) 一  建立一個具體傳輸服務的Socket。

      1-03、int WSAGetLastError() 一 擷取使用Windows Socket函式失敗時的錯誤訊息。

      1-04、IntPtr gethostbyname(IntPtr name)

          一 傳入DNS名稱透過DNS Server取得Host端的網路位址和其他資訊。

          一 一個DNS名稱可能不只對應一個網路位址,但一個網路位址只可以對應一個DNS名稱。

      1-05、IntPtr gethostbyaddr(ref uint addr, int type,int len) 一 同上,但是使用網路位址來取得資訊。

      1-06、int gethostname(IntPtr name,int namelen) 一 取得本機的網路名稱。

      1-07、uint inet_addr(Intptr cp) 一 將帶有dot的字串IP轉換成網路格式(big-endian)的uint。

      1-08、string inet_ntoa(uint sin_addr) 一  將網路格式(big-endian)的ushort轉換成帶有dot的字串IP。

      1-09、ushort htons(ushort hostshort) 一 將ushort 轉換成網路格式(big-endia)的ushort。     

      1-10、int setsockopt(int s,int level,int optname,IntPtr optval,int optlen)

          一  設定Socket 選項的函式。

               Ex. send/receive timeout or 設定IP_HDRINCL 由應用程式產生IP Header。

      1-11、int sendto(int s,IntPtr buf,int len,int flags,ref SOCKADDR_IN to,int tolen)

           一 傳送資料至Host端,常用於UDP協定。

      1-12、int select(int nfds,IntPtr readfds,IntPtr writefds,IntPtr exceptfds,ref timeval timeout)

           一 檢查指定的Socket是否有接收到資料或是否可以傳送資料。

      1-13、int recvfrom(int s,IntPtr buf,int len,int flags,IntPtr from,ref int fromlen)

           一 擷取由Host回傳的訊息,常用於接收UDP協定。

      1-14、int closesocket(int s) 一 關閉指定的Socket。

      1-15、int WSACleanup() 一 終止使用Windows Socket 2 DLL (to close WSAStartup)

 

二、實作Ping和Trace功能時,在成功的調用WAStartup函式之後;由於必須讀取網路封包的標頭(Header)

      資訊,因此必須使用SOCK_RAW即原始的SOCKET,來取得相關協定的標頭(Header)。

      設定方式如下:

      Ex.   openSocket = socket(AF_INET,SOCK_RAW,protocol) 

              AF_INET:設定使用IPv4(Inter Protocol Version 4)    PS. IPv6是使用AF_INET6

              SOCK_RAW:接收/傳送包含IP Header 和 UDP/TCP/ICMP Header

              protocol:設定接收/傳送封包的傳送協定。

      PS. 由於使用SOCK_RAW程式必須有管理人權限,因此可以執行下列的步驟。

            系統將會自動詢問(Vista) 是否以管理人權限來執行。

            1. 在專案目錄下建立manifest File內容如下。

                Ex. .../PingTrace/PringTrace/PingTrace.manifest     

                <?xml version="1.0" encoding="utf-8" ?>
                <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
                <assemblyIdentity
                                      version="1.0.0.0"
                                      processorArchitecture="X86"
                                      name="someExecName"
                                      type="win32"  />
                 <description>Your Program Description</description>
                 <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
                 <security>
                 <requestedPrivileges>
                          <requestedExecutionLevel level="requireAdministrator" /> <==主要在這一行
                  </requestedPrivileges>
                  </security>
                  </trustInfo>
                  </assembly>

            2. Project -> Properties

              manifest.jpg             

三、實作Ping函式主要是對Host端傳送ICMP封包,當Host端接收後則會回覆ICMP封包。

      如果無法抵達Host端,則會由連線中的某路由器返回'ICMP_DESTUNREACH'錯誤訊息,

      但如果Host端已經關機或Host端設定對ICMP不做回應是則必須自行設定超時的功能。

      實作Ping函式主要有下列五個步驟:
 
      3.1、對建立的socket使用setsockopt函式設定SO_RCVTIMEO/SO_SNDTIMEO

              參數來完成timeout的功能。

      3.2、建立ICMP封包. 

         3.2.1、先建立ICMP Header 並將Type Field 設為ICMP_ECHO。

                    PS. 其他有關ICMP Header設定可參考Internet Control Message Protocol 。

         3.2.2、計算ICMP Checksum值,公式如下:

            1. 首先將ICMP Header中的Checksum設定零。

            2. 以Word為單位(2byte),累加所有ICMP Package的資料。

            3. 將累加後所得的值,分成高位元組(High Byte)和低位元組(Low Byte)再將兩位元組相加。

            4. 若兩位元組相加後,產生溢位(overflow)則必須再將溢位值回加至該位元組。

            5. 最後所得的位元組取1's Complment(補數),即為該ICMP封包的Checksum。

      3.3、設定SOCKADDR_IN structure和使用sendto函式傳送ICMP封包。

      3.4、使用recvfrom接收ICMP封包並進行分析,回傳的資料中是包含IP Header的資訊。

            分析判斷條件如下:

            1. 判斷回傳封包是否大於等28 Bytes  [ IP Header (20 bytes) + ICMP Header (8 bytes) ]。

            2. 檢查ICMP Header中的Identifier,確認回傳的封包是否是回應給這個應用程式。

                PS. 有可能其他的應用程式也在傳送ICMP封包。

            3. 檢查ICMP Header中的Type是否為ICMP_ECHOREPLY。

      3.5、計算回應時間,從傳送到接收的時間差並除2(來回的時間)。

 

四、實作Trace函式可以使用UDP或ICMP協定來完成;不管是用UDP或ICMP都是使用相同的原理

      來完成Trace的功能不同的只是傳送的封包不同而已。 實作Trace函式的原理是調整對HOST端

      所發出封包的TTL(存活時間)值,來得到封包傳遞的路徑。

 

      使用ICMP實作Trace函式主要有下列六個步驟:

      4.1.1、對建立的socket使用setsockopt函式設定SO_RCVTIMEO/SO_SNDTIMEO

                 參數來完成timeout的功能。

     4.1.2、建立ICMP封包. 

         4.1.2.1、先建立ICMP Header 並將Type Field 設為ICMP_ECHO。

               PS. 其他有關ICMP Header設定可參考Internet Control Message Protocol 。

         4.1.2.2、計算ICMP Checksum值,公式如下:

            1. 首先將ICMP Header中的Checksum設定零。

            2. 以Word為單位(2byte),累加所有ICMP Package的資料。

            3. 將累加後所得的值,分成高位元組(High Byte)和低位元組(Low Byte)再將兩位元組相加。

            4. 若兩位元組相加後,產生溢位(overflow)則必須再將溢位值回加至該位元組。

            5. 最後所得的位元組取1's Complment(補數),即為該ICMP封包的Checksum。

   4.1.3、對建立的Socket使用setsockopt函式設定IP_TTL參數。

   4.1.4、設定SOCKADDR_IN structure和使用sendto函式傳送ICMP封包。

   4.1.5、使用recvfrom接收ICMP封包並進行分析,回傳的資料中是包含IP Header的資訊。

              分析判斷條件如下:

             1. 判斷回傳封包是否大於等28 Bytes  [ IP Header (20 bytes) + ICMP Header (8 bytes) ]。

             2. 檢查ICMP Header中的Identifier,確認回傳的封包是否是回應給這個應用程式。

                 PS. 有可能其他的應用程式也在傳送ICMP封包。

             3. 檢查ICMP Header中的Type是否為ICMP_ECHOREPLY; 若不是則將TTL值加一

                  再重新傳送ICMP封包。            

   4.1.6、計算回應時間,從傳送到接收的時間差並除2(來回的時間)。


    
     使用UDP實作Trace函式主要有下列七個步驟:

   4.2.1、對建立的socket使用setsockopt函式設定IP_HDRINCL參數,

                告知socket由應用程式自行提供IP Header。

   4.2.2、建立IP Header和UDP封包。

       4.2.2.1、首先必須先建立並設定IP Header的資料,每當要延長TTL值時必須在

                    IP Header中的TTL Field進行修改。

       4.2.2.2、建立並設定UDP Header的資料。

       4.2.2.3、計算UDP的Checksum,計算步驟如下:

              1. 建立並設定Pseudo Header,但只用於計算UDP Package的Checksum。

                  實際上傳送的封包並不包含Pseudo Header,排列順序如下:

                               ---------------------------------------------------------------
                              |  Pseudo Header   |   UDP Header    |     UDP DATA     |           
                               ---------------------------------------------------------------
                              |----- 12 Bytes -----|---- 8  Bytes ----|

              2. 以Word為單位(2byte),累加所有Pseudo Header和UDP Package的資料。

              3. 將累加後所得的值,分成高位元組(High Byte)和低位元組(Low Byte)再將兩位元組相加。

              4. 若兩位元組相加後,產生溢位(overflow)則必須再將溢位值回加至該位元組。

              5. 最後所得的位元組取1's Complment(補數),即為該UDP封包的Checksum。             

              PS. 1 有關IP Header的設定可參考Internet Protocol 。 

                    2 有關UDP Header的設定可參考User Datagram Protocol

                    3 有關Pesudo Header的設定可參考Pseudo Header 。

   4.2.3、設定SOCKADDR_IN structure和使用sendto函式傳送包含IP Header的UDP封包。

   4.2.4、使用select函式來設定timeout的功能。

   4.2.5、使用recvfrom接收ICMP封包並進行分析,回傳的資料中是包含IP Header的資訊。

              分析判斷條件如下:

              1. 判斷IP Header中的Protocol Field是否為IPPROTO_ICMP。

              2. 判斷IP Header中的Soruce Address Field是否與Destination Address相同。

              3. 判斷ICMP Header中Type Field是否為ICMP_DESTUNREACH,若是則表示找不到Host端

              4. 如果2,3項皆否, 則將TTL值加一再重新傳送UDP封包。

   4.2.6、計算回應時間,從傳送到接收的時間差並除2(來回的時間)。

 

Download :  PingTrace (Source Code)    PingTrace(EXE)

Result :

 Ping Result-

          ping.jpg

ICMP Trace Result-

          ICMPTrace.jpg

UDP Trace Result-

      UDPTrace.jpg

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 yunjuihuang 的頭像
    yunjuihuang

    瑞の資訊備忘錄

    yunjuihuang 發表在 痞客邦 留言(0) 人氣()