1 #Region "Microsoft.VisualBasic::e6c07b21d04f75b05dedf7024803d15c, Microsoft.VisualBasic.Core\ApplicationServices\Tools\Network\Tcp\PingUtility.vb"
2
3     ' Author:
4     
5     '       asuka (amethyst.asuka@gcmodeller.org)
6     '       xie (genetics@smrucc.org)
7     '       xieguigang (xie.guigang@live.com)
8     
9     ' Copyright (c) 2018 GPL3 Licensed
10     
11     
12     ' GNU GENERAL PUBLIC LICENSE (GPL3)
13     
14     
15     ' This program is free software: you can redistribute it and/or modify
16     ' it under the terms of the GNU General Public License as published by
17     ' the Free Software Foundation, either version 3 of the License, or
18     ' (at your option) any later version.
19     
20     ' This program is distributed in the hope that it will be useful,
21     ' but WITHOUT ANY WARRANTY; without even the implied warranty of
22     ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     ' GNU General Public License for more details.
24     
25     ' You should have received a copy of the GNU General Public License
26     ' along with this program. If not, see <http://www.gnu.org/licenses/>.
27
28
29
30     ' /********************************************************************************/
31
32     ' Summaries:
33
34     '     Module PingUtility
35     
36     
37     '         Enum ConnectionState
38     
39     
40     
41     
42     '  
43     
44     '     FunctionInternetGetConnectedState, IsOffline, Ping
45     
46     
47     ' /********************************************************************************/
48
49 #End Region
50
51 Imports System.Collections.Generic
52 Imports System.Text
53 Imports System.Net
54 Imports System.Net.NetworkInformation
55 Imports System.Runtime.InteropServices
56 Imports System.Threading
57 Imports System.IO
58
59 Namespace Net
60
61     ''' <summary>
62     ''' http://www.codeproject.com/Articles/18635/Ping-exe-replica-in-C
63     ''' 
64     ''' Ping.exe replica in C# 2.0
65     '''
66     ''' Stefan Prodan, 3 May 2007 CPOL
67     ''' Usage example of the System.Net.NetworkInformation.Ping.
68     ''' </summary>
69     ''' <remarks></remarks>
70     Public Module PingUtility
71
72         <Flags> Public Enum ConnectionState As Integer
73             INTERNET_CONNECTION_MODEM = &H1
74             INTERNET_CONNECTION_LAN = &H2
75             INTERNET_CONNECTION_PROXY = &H4
76             INTERNET_RAS_INSTALLED = &H10
77             INTERNET_CONNECTION_OFFLINE = &H20
78             INTERNET_CONNECTION_CONFIGURED = &H40
79         End Enum
80
81         <DllImport("wininet"CharSet:=CharSet.Auto)> Public Function InternetGetConnectedState(ByRef lpdwFlags As ConnectionState, dwReserved As IntegerAs Boolean
82         End Function
83
84         Public Function IsOffline() As Boolean
85             Dim state As ConnectionState = 0
86             InternetGetConnectedState(state, 0)
87             If (CInt(ConnectionState.INTERNET_CONNECTION_OFFLINE) And CInt(state)) <> 0 Then
88                 Return True
89             End If
90
91             Return False
92         End Function
93
94         ''' <summary>
95         ''' 返回与目标远程机器之间的平均通信时间长度
96         ''' </summary>
97         ''' <param name="IP"></param>
98         ''' <param name="out">Default is console.</param>
99         ''' <returns></returns>
100         ''' <remarks></remarks>
101         Public Function Ping(IP As IPAddress, Optional timeOut As UInteger = 3000, Optional out As StreamWriter = NothingAs Double
102             'set options ttl=128 and no fragmentation
103             Dim options As New PingOptions(128, True)
104
105             'create a Ping object
106             Dim pingTools As New System.Net.NetworkInformation.Ping()
107
108             '32 empty bytes buffer
109             Dim data As Byte() = New Byte(31) {}
110
111             Dim received As Integer = 0
112             Dim responseTimes As New List(Of Long)()
113
114             If out Is Nothing Then
115                 out = New StreamWriter(Console.OpenStandardOutput)
116             End If
117
118             'ping 4 times
119             For i As Integer = 0 To 3
120                 Dim reply As PingReply
121
122                 Try
123                     reply = pingTools.Send(IP, timeOut, data, options)
124                 Catch ex As Exception
125                     received += 1
126                     responseTimes.Add(10 * 1000)
127                     Continue For
128                 End Try
129
130                 If reply Is Nothing Then
131                     Call "Ping failed for an unknown reason".__DEBUG_ECHO
132                     Continue For
133                 End If
134
135                 Dim msg$
136
137                 Select Case reply.Status
138
139                     Case IPStatus.Success
140                         If reply.Options Is Nothing Then
141                             msg = $"Reply from {reply.Address}: bytes={reply.Buffer.Length} time={reply.RoundtripTime}ms"
142                         Else
143                             msg = $"Reply from {reply.Address}: bytes={reply.Buffer.Length} time={reply.RoundtripTime}ms TTL={reply.Options.Ttl}"
144                         End If
145
146                         received += 1
147                         responseTimes.Add(reply.RoundtripTime)
148
149                     Case IPStatus.TimedOut
150                         msg = "Request timed out."
151
152                     Case Else
153                         msg = $"Ping failed {reply.Status.ToString}"
154
155                 End Select
156
157                 Call out.WriteLine(msg$)
158             Next
159
160             'statistics calculations
161             Dim averageTime As Long = -1
162             Dim minimumTime As Long = 0
163             Dim maximumTime As Long = 0
164
165             For i As Integer = 0 To responseTimes.Count - 1
166                 If i = 0 Then
167                     minimumTime = responseTimes(i)
168                     maximumTime = responseTimes(i)
169                 Else
170                     If responseTimes(i) > maximumTime Then
171                         maximumTime = responseTimes(i)
172                     End If
173                     If responseTimes(i) < minimumTime Then
174                         minimumTime = responseTimes(i)
175                     End If
176                 End If
177                 averageTime += responseTimes(i)
178             Next
179
180             Dim statistics As New StringBuilder()
181             statistics.AppendFormat("Ping statistics for {0}:", IP.ToString())
182             statistics.AppendLine()
183             statistics.AppendFormat("   Packets: Sent = 4, Received = {0}, Lost = {1} <{2}% loss>,", received, 4 - received, Convert.ToInt32(((4 - received) * 100) \ 4))
184             statistics.AppendLine()
185             statistics.Append("Approximate round trip times in milli-seconds:")
186             statistics.AppendLine()
187
188             'show only if loss is not 100%
189             If averageTime <> -1 Then
190                 statistics.AppendFormat("    Minimum = {0}ms, Maximum = {1}ms, Average = {2}ms", minimumTime, maximumTime, CLng(averageTime \ received))
191             End If
192
193             out.WriteLine()
194             out.WriteLine(statistics.ToString())
195             out.WriteLine()
196
197             If received <= 0 Then  'Ping不通
198                 Return Double.MaxValue
199             End If
200
201             Return averageTime \ received
202         End Function
203     End Module
204 End Namespace