This repository has been archived by the owner on Mar 7, 2022. It is now read-only.
/
Ping.java
370 lines (314 loc) · 11.8 KB
/
Ping.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
package exp.libs.warp.net.ping;
import java.util.List;
import exp.libs.envm.Charset;
import exp.libs.utils.num.NumUtils;
import exp.libs.utils.os.OSUtils;
import exp.libs.utils.other.StrUtils;
import exp.libs.utils.verify.RegexUtils;
import exp.libs.warp.cmd.CmdUtils;
import exp.libs.warp.io.flow.StringFlowReader;
/**
* <pre>
* 简单的ping操作
* </pre>
* <br/><B>PROJECT : </B> exp-libs
* <br/><B>SUPPORT : </B> <a href="http://www.exp-blog.com" target="_blank">www.exp-blog.com</a>
* @version 2018-06-27
* @author EXP: 272629724@qq.com
* @since jdk版本:jdk1.6
*/
public class Ping {
/** ping命令 */
private final static String CMD_PING = "ping";
/** tracert命令 */
private final static String CMD_TRACERT = OSUtils.isWin() ?
"tracert -d -w 1 " : "traceroute -w 0.1 -n -q 1 ";
/** 私有化构造函数 */
protected Ping() {}
/**
* 执行ping操作
* @param host 被ping的主机, 可以是IP(如192.168.11.22) 或 域名(如:www.exp-blog.com)
* @return ping结果
*/
public static Pong ping(String host) {
return ping(host, 4, 0, 0);
}
/**
* 执行ping操作
* @param host 被ping的主机, 可以是IP(如192.168.11.22) 或 域名(如:www.exp-blog.com)
* @param count 执行ping的次数(默认4次)
* @return ping结果
*/
public static Pong ping(String host, int count) {
return ping(host, count, 0, 0);
}
/**
* 执行ping操作
* @param host 被ping的主机, 可以是IP(如192.168.11.22) 或 域名(如:www.exp-blog.com)
* @param count 执行ping的次数(默认4次)
* @param timeout 仅linux有效:命令超时(s). 若超过这个时间则ping命令强制结束
* @param intervalSecond 仅linux有效:执行ping的间隔(s), 默认值1秒
* @return ping结果
*/
public static Pong ping(String host,
int count, int timeout, double intervalSecond) {
String cmd = getPingCommand(host, count, timeout, intervalSecond);
return toPong(CmdUtils.execute(cmd).getInfo());
}
/**
* 组装ping命令
* @param host 被ping的主机, 可以是IP(如192.168.11.22) 或 域名(如:www.exp-blog.com)
* @param count 执行ping的次数(默认4次)
* @param timeout 仅linux有效:命令超时(s). 若超过这个时间则ping命令强制结束
* @param intervalSecond 仅linux有效:执行ping的间隔(s), 默认值1秒
* @return ping命令
*/
private static String getPingCommand(String host,
int count, int timeout, double intervalSecond) {
StringBuilder cmd = new StringBuilder(CMD_PING);
cmd.append(" ").append(host);
count = (count <= 0 ? 4 : count); // 默认ping 4次
cmd.append(OSUtils.isWin() ? " -n " : " -c ").append(count);
if(OSUtils.isUnix()) {
if(timeout > 0) {
cmd.append(" -w ").append(timeout);
} else if(OSUtils.isUnix()) {
cmd.append(" -w 10"); // linux环境强制指定超时(否则会无限阻塞)
}
if(intervalSecond > 0) {
cmd.append(" -i ").append(intervalSecond);
}
}
return cmd.toString();
}
/**
* 把 [ping执行结果] 转换成 [pong对象]
* @param pingRst ping执行结果
* @return pong对象
*/
protected static Pong toPong(String pingRst) {
return OSUtils.isWin() ?
_toPongByWin(pingRst) : _toPongByLinux(pingRst);
}
/**
* 把 [win平台下的ping执行结果] 转换成 [pong对象]
* @param pingRst win平台下的ping执行结果
* @return
*/
private static Pong _toPongByWin(String pingRst) {
return StrUtils.containsCh(pingRst) ?
_toPongByWinCh(pingRst) : _toPongByWinEn(pingRst);
}
/**
* 把 [(英文版)win平台下的ping执行结果] 转换成 [pong对象]
* @param pingRst (英文版)win平台下的ping执行结果
* <PRE>
* PING IP:
Pinging 183.232.231.173 with 32 bytes of data:
* 或 PING 域名:
Pinging www.exp-blog.com [183.232.231.173] with 32 bytes of data:
Reply from 183.232.231.173: bytes=32 time<1ms TTL=50
Reply from 183.232.231.173: bytes=32 time=6ms TTL=50
Reply from 183.232.231.173: bytes=32 time=7ms TTL=50
Request timed out.
Ping statistics for 183.232.231.173:
Packets: Sent = 4, Received = 3, Lost = 1 (25% loss),
Approximate round trip times in milli-seconds:
Minimum = 6ms, Maximum = 10ms, Average = 8ms
</PRE>
* @return pong对象
*/
private static Pong _toPongByWinEn(String pingRst) {
Pong pong = new Pong();
StringFlowReader sfr = new StringFlowReader(pingRst, Charset.DEFAULT);
while(sfr.hasNextLine()) {
String line = sfr.readLine().trim();
if(StrUtils.isEmpty(line)) {
continue;
} else if(line.startsWith("Pinging")) {
int bytes = NumUtils.toInt(
RegexUtils.findFirst(line, "(\\d+) bytes"), -1);
pong.setPacketBytes(bytes);
} else if(line.startsWith("Reply")) {
line = line.replace("<1ms", "=0ms");
List<String> nums = RegexUtils.findGroups(line,
"time=([\\d\\.]+)ms TTL=(\\d+)");
double rtt = NumUtils.toDouble(nums.get(1), 0);
int ttl = NumUtils.toInt(nums.get(2), 0);
pong.addRTT(rtt);
pong.setTTL(ttl);
} else if(line.startsWith("Request timed out")) {
pong.addRTT(-1);
} else if(line.contains("statistics")) {
String snkIp = RegexUtils.findFirst(line, "for ([\\d\\.]+)");
pong.setSnkIp(snkIp);
} else if(line.startsWith("Packets")) {
List<String> nums = RegexUtils.findGroups(line,
"Sent = (\\d+), Received = (\\d+), Lost = (\\d+) \\(([\\d\\.]+)% loss");
int sent = NumUtils.toInt(nums.get(1), 0);
int recv = NumUtils.toInt(nums.get(2), 0);
int lost = NumUtils.toInt(nums.get(3), 0);
double loss = NumUtils.toDouble(nums.get(4), 0);
pong.setSent(sent);
pong.setRecv(recv);
pong.setLost(lost);
pong.setLoss(loss);
} else if(line.startsWith("Minimum")) {
List<String> nums = RegexUtils.findGroups(line,
"Minimum = (\\d+)ms, Maximum = (\\d+)ms, Average = (\\d+)ms");
double minRTT = NumUtils.toDouble(nums.get(1), 0);
double maxRTT = NumUtils.toDouble(nums.get(2), 0);
double avgRTT = NumUtils.toDouble(nums.get(3), 0);
pong.setMinRTT(minRTT);
pong.setMaxRTT(maxRTT);
pong.setAvgRTT(avgRTT);
}
}
sfr.close();
return pong;
}
/**
* 把 [(中文版)win平台下的ping执行结果] 转换成 [pong对象]
* @param pingRst (中文版)win平台下的ping执行结果
* <PRE>
* PING IP:
正在 Ping 183.232.231.173 具有 32 字节的数据:
* 或 PING 域名:
正在 Ping www.exp-blog.com [183.232.231.172] 具有 32 字节的数据:
来自 183.232.231.172 的回复: 字节=32 时间<1ms TTL=54
来自 183.232.231.172 的回复: 字节=32 时间=58ms TTL=54
来自 183.232.231.172 的回复: 字节=32 时间=69ms TTL=54
请求超时。
183.232.231.172 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 3,丢失 = 1 (25% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 51ms,最长 = 69ms,平均 = 59ms
</PRE>
* @return pong对象
*/
private static Pong _toPongByWinCh(String pingRst) {
Pong pong = new Pong();
StringFlowReader sfr = new StringFlowReader(pingRst, Charset.DEFAULT);
while(sfr.hasNextLine()) {
String line = sfr.readLine().trim();
if(StrUtils.isEmpty(line)) {
continue;
} else if(line.startsWith("正在 Ping")) {
int bytes = NumUtils.toInt(
RegexUtils.findFirst(line, "(\\d+) 字节"), -1);
pong.setPacketBytes(bytes);
} else if(line.startsWith("来自")) {
line = line.replace("<1ms", "=0ms");
List<String> nums = RegexUtils.findGroups(line,
"时间=([\\d\\.]+)ms TTL=(\\d+)");
double rtt = NumUtils.toDouble(nums.get(1), 0);
int ttl = NumUtils.toInt(nums.get(2), 0);
pong.addRTT(rtt);
pong.setTTL(ttl);
} else if(line.startsWith("请求超时")) {
pong.addRTT(-1);
} else if(line.contains("统计")) {
String snkIp = RegexUtils.findFirst(line, "([\\d\\.]+) 的 Ping");
pong.setSnkIp(snkIp);
} else if(line.startsWith("数据包")) {
List<String> nums = RegexUtils.findGroups(line,
"已发送 = (\\d+),已接收 = (\\d+),丢失 = (\\d+) \\(([\\d\\.]+)% 丢失");
int sent = NumUtils.toInt(nums.get(1), 0);
int recv = NumUtils.toInt(nums.get(2), 0);
int lost = NumUtils.toInt(nums.get(3), 0);
double loss = NumUtils.toDouble(nums.get(4), 0);
pong.setSent(sent);
pong.setRecv(recv);
pong.setLost(lost);
pong.setLoss(loss);
} else if(line.startsWith("最短")) {
List<String> nums = RegexUtils.findGroups(line,
"最短 = (\\d+)ms,最长 = (\\d+)ms,平均 = (\\d+)ms");
double minRTT = NumUtils.toDouble(nums.get(1), 0);
double maxRTT = NumUtils.toDouble(nums.get(2), 0);
double avgRTT = NumUtils.toDouble(nums.get(3), 0);
pong.setMinRTT(minRTT);
pong.setMaxRTT(maxRTT);
pong.setAvgRTT(avgRTT);
}
}
sfr.close();
return pong;
}
/**
* 把 [linux平台下的ping执行结果] 转换成 [pong对象]
* @param pingRst linux平台下的ping执行结果
* <PRE>
* PING IP:
PING 220.181.112.244 (220.181.112.244) 56(84) bytes of data.
* 或 PING 域名:
PING www.exp-blog.com (220.181.112.244) 56(84) bytes of data.
64 bytes from 220.181.112.244 (220.181.112.244): icmp_seq=1 ttl=55 time<1 ms
64 bytes from 220.181.112.244 (220.181.112.244): icmp_seq=2 ttl=55 time=43.9 ms
64 bytes from 220.181.112.244 (220.181.112.244): icmp_seq=3 ttl=55 time=43.9 ms
64 bytes from 220.181.112.244 (220.181.112.244): icmp_seq=4 ttl=55 time=43.9 ms
--- www.exp-blog.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3003ms
rtt min/avg/max/mdev = 43.928/43.953/43.989/0.257 ms
</PRE>
* @return pong对象
*/
private static Pong _toPongByLinux(String pingRst) {
Pong pong = new Pong();
StringFlowReader sfr = new StringFlowReader(pingRst, Charset.DEFAULT);
while(sfr.hasNextLine()) {
String line = sfr.readLine().trim();
if(StrUtils.isEmpty(line)) {
continue;
} else if(line.startsWith("PING")) {
String snkIp = RegexUtils.findFirst(line, " \\(([\\d\\.]+)\\) ");
pong.setSnkIp(snkIp);
} else if(line.contains("bytes from")) {
line = line.replace("<1 ms", "=0 ms");
List<String> nums = RegexUtils.findGroups(line,
"(\\d+) bytes from.*?ttl=(\\d+) time=([\\d\\.]+) ms");
int bytes = NumUtils.toInt(nums.get(1), 0);
int ttl = NumUtils.toInt(nums.get(2), 0);
double rtt = NumUtils.toDouble(nums.get(3), 0);
pong.setPacketBytes(bytes);
pong.setTTL(ttl);
pong.addRTT(rtt);
} else if(line.contains("packets transmitted")) {
List<String> nums = RegexUtils.findGroups(line,
"(\\d+) packets transmitted, (\\d+) received, ([\\d\\.]+)% packet loss, time ([\\d\\.]+)ms");
int sent = NumUtils.toInt(nums.get(1), 0);
int recv = NumUtils.toInt(nums.get(2), 0);
double loss = NumUtils.toDouble(nums.get(3), 0);
double totalRTT = NumUtils.toDouble(nums.get(4), 0);
pong.setSent(sent);
pong.setRecv(recv);
pong.setLost(sent - recv);
pong.setLoss(loss);
pong.setTotalRTT(totalRTT);
} else if(line.startsWith("rtt")) {
List<String> nums = RegexUtils.findGroups(line,
"([\\d\\.]+)/([\\d\\.]+)/([\\d\\.]+)/([\\d\\.]+) ms");
double minRTT = NumUtils.toDouble(nums.get(1), 0);
double avgRTT = NumUtils.toDouble(nums.get(2), 0);
double maxRTT = NumUtils.toDouble(nums.get(3), 0);
double mdevRTT = NumUtils.toDouble(nums.get(4), 0);
pong.setMinRTT(minRTT);
pong.setMaxRTT(maxRTT);
pong.setAvgRTT(avgRTT);
pong.setMdevRTT(mdevRTT);
}
}
sfr.close();
return pong;
}
/**
* 执行tracert操作
*
* @param host 被tracert的主机, 可以是IP(如192.168.11.22) 或 域名(如:www.exp-blog.com)
* @return tracert结果
*/
public static String tracert(String host) {
String cmd = StrUtils.concat(CMD_TRACERT, host);
return CmdUtils.execute(cmd).getInfo();
}
}