Source code: com/act365/net/ping/Ping.java
1 /*
2 * JSocket Wrench
3 *
4 * Copyright (C) act365.com October 2003
5 *
6 * Web site: http://www.act365.com/wrench
7 * E-mail: developers@act365.com
8 *
9 * The JSocket Wrench library adds support for low-level Internet protocols
10 * to the Java programming language.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the Free
14 * Software Foundation; either version 2 of the License, or (at your option)
15 * any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
20 * Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * this program; if not, write to the Free Software Foundation, Inc.,
24 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27 package com.act365.net.ping ;
28
29 import com.act365.net.*;
30 import com.act365.net.icmp.*;
31
32 import java.net.*;
33 import java.util.*;
34
35 /**
36 Implements the well-known ping network utility.
37 */
38
39 public class Ping {
40
41 DatagramSocket socket ;
42
43 int transmitted ;
44
45 boolean isinterrupted ;
46
47 /**
48 Creates a Ping object to listen for ICMP messages.
49 */
50
51 public Ping( DatagramSocket socket , int transmitted ){
52 this.socket = socket ;
53 this.transmitted = transmitted ;
54 isinterrupted = false ;
55 }
56
57 /**
58 Interrupts the receive cycle.
59 */
60
61 public void interrupt(){
62 isinterrupted = true ;
63 }
64
65 /**
66 Listens for ICMP packets.
67 */
68
69 public void receive() {
70
71 try {
72
73 final int maxdatagramlength = 512 ;
74
75 byte[] buffer = new byte[ maxdatagramlength ];
76
77 DatagramPacket packet ;
78
79 ICMPReader reader = new ICMPReader( (short) socket.hashCode() );
80
81 ICMPMessage message = null ;
82
83 int received = 0 ;
84
85 float sumdt = 0 ,
86 mindt = Float.MAX_VALUE ,
87 maxdt = Float.MIN_VALUE ;
88
89 try {
90 socket.setSoTimeout( 2500 );
91 } catch ( SocketException e ){
92 }
93
94 while( !( transmitted >= 0 && received >= transmitted ) && ! isinterrupted ){
95 packet = new DatagramPacket( buffer , maxdatagramlength );
96 socket.receive( packet );
97
98 if( ( message = reader.read( packet.getData() , packet.getLength() , 20 , false ) ) != null ){
99
100 long t1 , t2 ;
101
102 float dt ;
103
104 switch( message.type ) {
105
106 case ICMP.ICMP_ECHOREPLY:
107
108 ++ received ;
109
110 System.out.print( message.data.length + 8 + " bytes from ");
111 System.out.print( packet.getAddress() + ": ");
112 System.out.print( "icmp_seq=" + message.sequence_number + " " );
113
114 if( message.data.length >= 8 ){
115
116 t1 = SocketUtils.longFromBytes( message.data , 0 );
117 t2 = new Date().getTime();
118
119 dt = t2 - t1 ;
120
121 sumdt += dt ;
122
123 if( dt < mindt ){
124 mindt = dt ;
125 }
126
127 if( dt > maxdt ){
128 maxdt = dt ;
129 }
130
131 System.out.println( "time=" + dt + " ms" );
132
133 } else {
134 System.out.println();
135 }
136 break;
137
138 case ICMP.ICMP_DEST_UNREACH:
139
140 throw new Exception("Host unreachable");
141 }
142 } else {
143 System.err.println("Null message received");
144 }
145 }
146
147 if( transmitted > 0 ){
148 System.out.println("----ping statistics----");
149 System.out.print( transmitted + " packets transmitted, " );
150 System.out.print( received + " packets received, " );
151 System.out.println( 100.0 * ( transmitted - received )/ transmitted + "% packet loss" );
152
153 if( sumdt > 0 && received > 0 ){
154 System.out.print("round-trip min/avg/max = ");
155 System.out.println( mindt + "/" + sumdt / received + "/" + maxdt + " ms" );
156 }
157 }
158
159 } catch ( Exception e ) {
160 System.err.println( e.getMessage() );
161 System.exit( 1 );
162 }
163 }
164
165 /**
166 Executes the Ping service.
167 Usage: <code>Ping -c count -s nbytes -p protocol -l localhost -t ttl hostname</code>.
168 <p><code>-c count</code> (optional) defines the number of packets to be broadcast.
169 By default, the broadcast will continue endlessly.
170 <p><code>-s nbytes</code> (optional) defines the number of bytes to appear
171 in each packet. The default is 56.
172 <p><code>-p protocol</code> (optional) defines the socket protocol to be used.
173 By default, ICMP will be used - the alternative is RawICMP.
174 <p><code>-l localhost</code> (optional) should be specified if the protocol
175 has been set to RawICMP. The information will be used to construct the IP header.
176 <p><code>-t ttl</code> (optional) is the time-to-live to be used if the RawICMP
177 protocol has been selected. The default is 64.
178 <p><code>hostname</code> define the remote host.
179 */
180
181 public static void main( String[] args ){
182
183 final String errortext = "Usage Ping -c count -s nbytes -p protocol -l localhost hostname";
184
185 if( args.length == 0 ){
186 System.err.println( errortext );
187 System.exit( 1 );
188 }
189
190 String hostname = args[ args.length - 1 ] ,
191 protocollabel = "ICMP",
192 localhost = null ;
193
194 int count = -1 ;
195
196 int i = -1 ,
197 nbytes = 56 ;
198
199 short ttl = 64 ;
200
201 while( ++ i < args.length - 1 ){
202
203 if( args[ i ].equals("-c") && i < args.length - 2 ){
204 try {
205 count = Integer.parseInt( args[ ++ i ] );
206 } catch( NumberFormatException e ){
207 System.err.println("Invalid packet count");
208 System.exit( 3 );
209 }
210 } else if( args[ i ].equals("-s") && i < args.length - 2 ){
211 try {
212 nbytes = Integer.parseInt( args[ ++ i ] );
213 } catch( NumberFormatException e ){
214 System.err.println("Invalid packet size");
215 System.exit( 4 );
216 }
217 } else if( args[ i ].equals("-t") && i < args.length - 2 ){
218 try {
219 ttl = Short.parseShort( args[ ++ i ] );
220 } catch( NumberFormatException e ){
221 System.err.println("Invalid time-to-live");
222 System.exit( 5 );
223 }
224 } else if( args[ i ].equals("-p") && i < args.length - 2 ){
225 protocollabel = args[ ++ i ];
226 if( ! protocollabel.equalsIgnoreCase("ICMP") &&
227 ! protocollabel.equalsIgnoreCase("RawICMP") ){
228 System.err.println("Unsupported protocol");
229 System.exit( 2 );
230 }
231 } else if( args[ i ].equals("-l") && i < args.length - 2 ){
232 localhost = args[ ++ i ];
233 } else {
234 System.err.println( errortext );
235 System.exit( 1 );
236 }
237 }
238
239 try {
240 SocketUtils.setProtocol( protocollabel );
241 } catch ( java.io.IOException e ){
242 System.err.println("Protocol not supported");
243 System.exit( 2 );
244 }
245
246 new SocketWrenchSession();
247
248 InetAddress hostaddr = null ,
249 localaddr = null ;
250
251 try {
252 hostaddr = InetAddress.getByName( hostname );
253 if( localhost instanceof String ){
254 localaddr = InetAddress.getByName( localhost );
255 }
256 } catch ( UnknownHostException e ) {
257 System.err.println( e.getMessage() );
258 System.exit( 6 );
259 }
260
261 DatagramSocket socket = null ;
262
263 try {
264 socket = new DatagramSocket();
265 } catch ( SocketException e ) {
266 System.err.println( e.getMessage() );
267 System.exit( 7 );
268 }
269
270 Ping receiver = new Ping( socket , count );
271
272 ( new PingSender( socket ,
273 hostaddr ,
274 localaddr ,
275 (short) socket.hashCode() ,
276 receiver ,
277 count ,
278 nbytes ,
279 ttl ) ).start();
280
281 receiver.receive();
282 }
283 }