KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > net > DatagramSocket


1 /*
2  * @(#)DatagramSocket.java 1.101 06/06/08
3  *
4  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.net;
9
10 import java.io.FileDescriptor JavaDoc;
11 import java.io.IOException JavaDoc;
12 import java.io.InterruptedIOException JavaDoc;
13 import java.nio.channels.DatagramChannel JavaDoc;
14 import java.security.AccessController JavaDoc;
15 import java.security.PrivilegedExceptionAction JavaDoc;
16
17 /**
18  * This class represents a socket for sending and receiving datagram packets.
19  *
20  * <p>A datagram socket is the sending or receiving point for a packet
21  * delivery service. Each packet sent or received on a datagram socket
22  * is individually addressed and routed. Multiple packets sent from
23  * one machine to another may be routed differently, and may arrive in
24  * any order.
25  *
26  * <p>UDP broadcasts sends are always enabled on a DatagramSocket.
27  * In order to receive broadcast packets a DatagramSocket
28  * should be bound to the wildcard address. In some
29  * implementations, broadcast packets may also be received when
30  * a DatagramSocket is bound to a more specific address.
31  * <p>
32  * Example:
33  * <code>
34  * DatagramSocket s = new DatagramSocket(null);
35  * s.bind(new InetSocketAddress(8888));
36  * </code>
37  * Which is equivalent to:
38  * <code>
39  * DatagramSocket s = new DatagramSocket(8888);
40  * </code>
41  * Both cases will create a DatagramSocket able to receive broadcasts on
42  * UDP port 8888.
43  *
44  * @author Pavani Diwanji
45  * @version 1.101, 06/08/06
46  * @see java.net.DatagramPacket
47  * @see java.nio.channels.DatagramChannel
48  * @since JDK1.0
49  */

50 public
51 class DatagramSocket {
52     /**
53      * Various states of this socket.
54      */

55     private boolean created = false;
56     private boolean bound = false;
57     private boolean closed = false;
58     private Object JavaDoc closeLock = new Object JavaDoc();
59
60     /*
61      * The implementation of this DatagramSocket.
62      */

63     DatagramSocketImpl JavaDoc impl;
64
65     /**
66      * Are we using an older DatagramSocketImpl?
67      */

68     boolean oldImpl = false;
69
70     /*
71      * Connection state:
72      * ST_NOT_CONNECTED = socket not connected
73      * ST_CONNECTED = socket connected
74      * ST_CONNECTED_NO_IMPL = socket connected but not at impl level
75      */

76     static final int ST_NOT_CONNECTED = 0;
77     static final int ST_CONNECTED = 1;
78     static final int ST_CONNECTED_NO_IMPL = 2;
79
80     int connectState = ST_NOT_CONNECTED;
81
82     /*
83      * Connected address & port
84      */

85     InetAddress JavaDoc connectedAddress = null;
86     int connectedPort = -1;
87
88     /**
89      * Connects this socket to a remote socket address (IP address + port number).
90      * Binds socket if not already bound.
91      * <p>
92      * @param addr The remote address.
93      * @param port The remote port
94      * @throws SocketException if binding the socket fails.
95      */

96     private synchronized void connectInternal(InetAddress JavaDoc address, int port) throws SocketException JavaDoc {
97         if (port < 0 || port > 0xFFFF) {
98             throw new IllegalArgumentException JavaDoc("connect: " + port);
99         }
100         if (address == null) {
101             throw new IllegalArgumentException JavaDoc("connect: null address");
102         }
103         if (isClosed())
104             return;
105         SecurityManager JavaDoc security = System.getSecurityManager();
106         if (security != null) {
107             if (address.isMulticastAddress()) {
108                 security.checkMulticast(address);
109             } else {
110                 security.checkConnect(address.getHostAddress(), port);
111                 security.checkAccept(address.getHostAddress(), port);
112             }
113         }
114
115     if (!isBound())
116       bind(new InetSocketAddress JavaDoc(0));
117
118     // old impls do not support connect/disconnect
119
if (oldImpl) {
120         connectState = ST_CONNECTED_NO_IMPL;
121     } else {
122         try {
123             getImpl().connect(address, port);
124
125         // socket is now connected by the impl
126
connectState = ST_CONNECTED;
127         } catch (SocketException JavaDoc se) {
128
129         // connection will be emulated by DatagramSocket
130
connectState = ST_CONNECTED_NO_IMPL;
131         }
132     }
133
134         connectedAddress = address;
135         connectedPort = port;
136     }
137
138
139     /**
140      * Constructs a datagram socket and binds it to any available port
141      * on the local host machine. The socket will be bound to the wildcard
142      * address, an IP address chosen by the kernel.
143      *
144      * <p>If there is a security manager,
145      * its <code>checkListen</code> method is first called
146      * with 0 as its argument to ensure the operation is allowed.
147      * This could result in a SecurityException.
148      *
149      * @exception SocketException if the socket could not be opened,
150      * or the socket could not bind to the specified local port.
151      * @exception SecurityException if a security manager exists and its
152      * <code>checkListen</code> method doesn't allow the operation.
153      *
154      * @see SecurityManager#checkListen
155      */

156     public DatagramSocket() throws SocketException JavaDoc {
157     // create a datagram socket.
158
createImpl();
159     try {
160         bind(new InetSocketAddress JavaDoc(0));
161     } catch (SocketException JavaDoc se) {
162         throw se;
163     } catch(IOException JavaDoc e) {
164         throw new SocketException JavaDoc(e.getMessage());
165     }
166     }
167
168     /**
169      * Creates an unbound datagram socket with the specified
170      * DatagramSocketImpl.
171      *
172      * @param impl an instance of a <B>DatagramSocketImpl</B>
173      * the subclass wishes to use on the DatagramSocket.
174      * @since 1.4
175      */

176     protected DatagramSocket(DatagramSocketImpl JavaDoc impl) {
177         if (impl == null)
178             throw new NullPointerException JavaDoc();
179     this.impl = impl;
180     checkOldImpl();
181     }
182
183     /**
184      * Creates a datagram socket, bound to the specified local
185      * socket address.
186      * <p>
187      * If, if the address is <code>null</code>, creates an unbound socket.
188      * <p>
189      * <p>If there is a security manager,
190      * its <code>checkListen</code> method is first called
191      * with the port from the socket address
192      * as its argument to ensure the operation is allowed.
193      * This could result in a SecurityException.
194      *
195      * @param bindaddr local socket address to bind, or <code>null</code>
196      * for an unbound socket.
197      *
198      * @exception SocketException if the socket could not be opened,
199      * or the socket could not bind to the specified local port.
200      * @exception SecurityException if a security manager exists and its
201      * <code>checkListen</code> method doesn't allow the operation.
202      *
203      * @see SecurityManager#checkListen
204      * @since 1.4
205      */

206     public DatagramSocket(SocketAddress JavaDoc bindaddr) throws SocketException JavaDoc {
207     // create a datagram socket.
208
createImpl();
209     if (bindaddr != null) {
210         bind(bindaddr);
211     }
212     }
213
214     /**
215      * Constructs a datagram socket and binds it to the specified port
216      * on the local host machine. The socket will be bound to the wildcard
217      * address, an IP address chosen by the kernel.
218      *
219      * <p>If there is a security manager,
220      * its <code>checkListen</code> method is first called
221      * with the <code>port</code> argument
222      * as its argument to ensure the operation is allowed.
223      * This could result in a SecurityException.
224      *
225      * @param port port to use.
226      * @exception SocketException if the socket could not be opened,
227      * or the socket could not bind to the specified local port.
228      * @exception SecurityException if a security manager exists and its
229      * <code>checkListen</code> method doesn't allow the operation.
230      *
231      * @see SecurityManager#checkListen
232      */

233     public DatagramSocket(int port) throws SocketException JavaDoc {
234     this(port, null);
235     }
236
237     /**
238      * Creates a datagram socket, bound to the specified local
239      * address. The local port must be between 0 and 65535 inclusive.
240      * If the IP address is 0.0.0.0, the socket will be bound to the
241      * wildcard address, an IP address chosen by the kernel.
242      *
243      * <p>If there is a security manager,
244      * its <code>checkListen</code> method is first called
245      * with the <code>port</code> argument
246      * as its argument to ensure the operation is allowed.
247      * This could result in a SecurityException.
248      *
249      * @param port local port to use
250      * @param laddr local address to bind
251      *
252      * @exception SocketException if the socket could not be opened,
253      * or the socket could not bind to the specified local port.
254      * @exception SecurityException if a security manager exists and its
255      * <code>checkListen</code> method doesn't allow the operation.
256      *
257      * @see SecurityManager#checkListen
258      * @since JDK1.1
259      */

260     public DatagramSocket(int port, InetAddress JavaDoc laddr) throws SocketException JavaDoc {
261     this(new InetSocketAddress JavaDoc(laddr, port));
262     }
263
264     private void checkOldImpl() {
265     if (impl == null)
266         return;
267     // DatagramSocketImpl.peekdata() is a protected method, therefore we need to use
268
// getDeclaredMethod, therefore we need permission to access the member
269
try {
270         AccessController.doPrivileged(new PrivilegedExceptionAction JavaDoc() {
271             public Object JavaDoc run() throws NoSuchMethodException JavaDoc {
272             Class JavaDoc[] cl = new Class JavaDoc[1];
273             cl[0] = DatagramPacket JavaDoc.class;
274             impl.getClass().getDeclaredMethod("peekData", cl);
275             return null;
276             }
277         });
278     } catch (java.security.PrivilegedActionException JavaDoc e) {
279         oldImpl = true;
280     }
281     }
282
283     static Class JavaDoc implClass = null;
284
285     void createImpl() throws SocketException JavaDoc {
286     if (impl == null) {
287         if (factory != null) {
288         impl = factory.createDatagramSocketImpl();
289         checkOldImpl();
290         } else {
291         if (implClass == null) {
292             String JavaDoc prefix = null;
293             try {
294             prefix = (String JavaDoc) AccessController.doPrivileged(
295                 new sun.security.action.GetPropertyAction("impl.prefix", "Plain"));
296             implClass = Class.forName("java.net."+prefix+"DatagramSocketImpl");
297             } catch (Exception JavaDoc e) {
298             System.err.println("Can't find class: java.net." +
299                        prefix +
300                        "DatagramSocketImpl: check impl.prefix property");
301             }
302             if (implClass == null)
303             implClass = java.net.PlainDatagramSocketImpl JavaDoc.class;
304         }
305         try {
306             impl = (DatagramSocketImpl JavaDoc) implClass.newInstance();
307         } catch (Exception JavaDoc e) {
308             throw new SocketException JavaDoc("can't instantiate DatagramSocketImpl");
309         }
310         // No need to do a checkOldImpl() here, we know it's an up to date
311
// SocketImpl!
312
if (!(impl instanceof java.net.PlainDatagramSocketImpl JavaDoc))
313             checkOldImpl();
314         }
315     }
316     // creates a udp socket
317
impl.create();
318     created = true;
319     }
320
321     /**
322      * Get the <code>DatagramSocketImpl</code> attached to this socket,
323      * creating it if necessary.
324      *
325      * @return the <code>DatagramSocketImpl</code> attached to that
326      * DatagramSocket
327      * @throws SocketException if creation fails.
328      * @since 1.4
329      */

330     DatagramSocketImpl JavaDoc getImpl() throws SocketException JavaDoc {
331     if (!created)
332         createImpl();
333     return impl;
334     }
335
336     /**
337      * Binds this DatagramSocket to a specific address & port.
338      * <p>
339      * If the address is <code>null</code>, then the system will pick up
340      * an ephemeral port and a valid local address to bind the socket.
341      *<p>
342      * @param addr The address & port to bind to.
343      * @throws SocketException if any error happens during the bind, or if the
344      * socket is already bound.
345      * @throws SecurityException if a security manager exists and its
346      * <code>checkListen</code> method doesn't allow the operation.
347      * @throws IllegalArgumentException if addr is a SocketAddress subclass
348      * not supported by this socket.
349      * @since 1.4
350      */

351     public synchronized void bind(SocketAddress JavaDoc addr) throws SocketException JavaDoc {
352     if (isClosed())
353         throw new SocketException JavaDoc("Socket is closed");
354     if (isBound())
355         throw new SocketException JavaDoc("already bound");
356     if (addr == null)
357         addr = new InetSocketAddress JavaDoc(0);
358     if (!(addr instanceof InetSocketAddress JavaDoc))
359         throw new IllegalArgumentException JavaDoc("Unsupported address type!");
360     InetSocketAddress JavaDoc epoint = (InetSocketAddress JavaDoc) addr;
361     if (epoint.isUnresolved())
362         throw new SocketException JavaDoc("Unresolved address");
363     SecurityManager JavaDoc sec = System.getSecurityManager();
364     if (sec != null) {
365         sec.checkListen(epoint.getPort());
366     }
367     try {
368         getImpl().bind(epoint.getPort(),
369                epoint.getAddress());
370     } catch (SocketException JavaDoc e) {
371         getImpl().close();
372         throw e;
373     }
374     bound = true;
375     }
376
377     /**
378      * Connects the socket to a remote address for this socket. When a
379      * socket is connected to a remote address, packets may only be
380      * sent to or received from that address. By default a datagram
381      * socket is not connected.
382      *
383      * <p>If the remote destination to which the socket is connected does not
384      * exist, or is otherwise unreachable, and if an ICMP destination unreachable
385      * packet has been received for that address, then a subsequent call to
386      * send or receive may throw a PortUnreachableException. Note, there is no
387      * guarantee that the exception will be thrown.
388      *
389      * <p>A caller's permission to send and receive datagrams to a
390      * given host and port are checked at connect time. When a socket
391      * is connected, receive and send <b>will not
392      * perform any security checks</b> on incoming and outgoing
393      * packets, other than matching the packet's and the socket's
394      * address and port. On a send operation, if the packet's address
395      * is set and the packet's address and the socket's address do not
396      * match, an IllegalArgumentException will be thrown. A socket
397      * connected to a multicast address may only be used to send packets.
398      *
399      * @param address the remote address for the socket
400      *
401      * @param port the remote port for the socket.
402      *
403      * @exception IllegalArgumentException if the address is null,
404      * or the port is out of range.
405      *
406      * @exception SecurityException if the caller is not allowed to
407      * send datagrams to and receive datagrams from the address and port.
408      *
409      * @see #disconnect
410      * @see #send
411      * @see #receive
412      */

413     public void connect(InetAddress JavaDoc address, int port) {
414     try {
415         connectInternal(address, port);
416     } catch (SocketException JavaDoc se) {
417         throw new Error JavaDoc("connect failed", se);
418     }
419     }
420
421     /**
422      * Connects this socket to a remote socket address (IP address + port number).
423      * <p>
424      * @param addr The remote address.
425      * @throws SocketException if the connect fails
426      * @throws IllegalArgumentException if addr is null or addr is a SocketAddress
427      * subclass not supported by this socket
428      * @since 1.4
429      * @see #connect
430      */

431     public void connect(SocketAddress JavaDoc addr) throws SocketException JavaDoc {
432     if (addr == null)
433         throw new IllegalArgumentException JavaDoc("Address can't be null");
434     if (!(addr instanceof InetSocketAddress JavaDoc))
435         throw new IllegalArgumentException JavaDoc("Unsupported address type");
436     InetSocketAddress JavaDoc epoint = (InetSocketAddress JavaDoc) addr;
437     if (epoint.isUnresolved())
438         throw new SocketException JavaDoc("Unresolved address");
439     connectInternal(epoint.getAddress(), epoint.getPort());
440     }
441
442     /**
443      * Disconnects the socket. This does nothing if the socket is not
444      * connected.
445      *
446      * @see #connect
447      */

448     public void disconnect() {
449     synchronized (this) {
450         if (isClosed())
451         return;
452         if (connectState == ST_CONNECTED) {
453             impl.disconnect ();
454         }
455         connectedAddress = null;
456         connectedPort = -1;
457         connectState = ST_NOT_CONNECTED;
458     }
459     }
460
461     /**
462      * Returns the binding state of the socket.
463      *
464      * @return true if the socket succesfuly bound to an address
465      * @since 1.4
466      */

467     public boolean isBound() {
468     return bound;
469     }
470
471     /**
472      * Returns the connection state of the socket.
473      *
474      * @return true if the socket succesfuly connected to a server
475      * @since 1.4
476      */

477     public boolean isConnected() {
478     return connectState != ST_NOT_CONNECTED;
479     }
480
481     /**
482      * Returns the address to which this socket is connected. Returns null
483      * if the socket is not connected.
484      *
485      * @return the address to which this socket is connected.
486      */

487     public InetAddress JavaDoc getInetAddress() {
488     return connectedAddress;
489     }
490
491     /**
492      * Returns the port for this socket. Returns -1 if the socket is not
493      * connected.
494      *
495      * @return the port to which this socket is connected.
496      */

497     public int getPort() {
498     return connectedPort;
499     }
500
501     /**
502      * Returns the address of the endpoint this socket is connected to, or
503      * <code>null</code> if it is unconnected.
504      * @return a <code>SocketAddress</code> representing the remote
505      * endpoint of this socket, or <code>null</code> if it is
506      * not connected yet.
507      * @see #getInetAddress()
508      * @see #getPort()
509      * @see #connect(SocketAddress)
510      * @since 1.4
511      */

512     public SocketAddress JavaDoc getRemoteSocketAddress() {
513     if (!isConnected())
514         return null;
515     return new InetSocketAddress JavaDoc(getInetAddress(), getPort());
516     }
517
518     /**
519      * Returns the address of the endpoint this socket is bound to, or
520      * <code>null</code> if it is not bound yet.
521      *
522      * @return a <code>SocketAddress</code> representing the local endpoint of this
523      * socket, or <code>null</code> if it is not bound yet.
524      * @see #getLocalAddress()
525      * @see #getLocalPort()
526      * @see #bind(SocketAddress)
527      * @since 1.4
528      */

529
530     public SocketAddress JavaDoc getLocalSocketAddress() {
531     if (!isBound())
532         return null;
533     return new InetSocketAddress JavaDoc(getLocalAddress(), getLocalPort());
534     }
535
536     /**
537      * Sends a datagram packet from this socket. The
538      * <code>DatagramPacket</code> includes information indicating the
539      * data to be sent, its length, the IP address of the remote host,
540      * and the port number on the remote host.
541      *
542      * <p>If there is a security manager, and the socket is not currently
543      * connected to a remote address, this method first performs some
544      * security checks. First, if <code>p.getAddress().isMulticastAddress()</code>
545      * is true, this method calls the
546      * security manager's <code>checkMulticast</code> method
547      * with <code>p.getAddress()</code> as its argument.
548      * If the evaluation of that expression is false,
549      * this method instead calls the security manager's
550      * <code>checkConnect</code> method with arguments
551      * <code>p.getAddress().getHostAddress()</code> and
552      * <code>p.getPort()</code>. Each call to a security manager method
553      * could result in a SecurityException if the operation is not allowed.
554      *
555      * @param p the <code>DatagramPacket</code> to be sent.
556      *
557      * @exception IOException if an I/O error occurs.
558      * @exception SecurityException if a security manager exists and its
559      * <code>checkMulticast</code> or <code>checkConnect</code>
560      * method doesn't allow the send.
561      * @exception PortUnreachableException may be thrown if the socket is connected
562      * to a currently unreachable destination. Note, there is no
563      * guarantee that the exception will be thrown.
564      * @exception java.nio.channels.IllegalBlockingModeException
565      * if this socket has an associated channel,
566      * and the channel is in non-blocking mode.
567      *
568      * @see java.net.DatagramPacket
569      * @see SecurityManager#checkMulticast(InetAddress)
570      * @see SecurityManager#checkConnect
571      * @revised 1.4
572      * @spec JSR-51
573      */

574     public void send(DatagramPacket JavaDoc p) throws IOException JavaDoc {
575     InetAddress JavaDoc packetAddress = null;
576     synchronized (p) {
577         if (isClosed())
578         throw new SocketException JavaDoc("Socket is closed");
579         if (connectState == ST_NOT_CONNECTED) {
580         // check the address is ok wiht the security manager on every send.
581
SecurityManager JavaDoc security = System.getSecurityManager();
582
583         // The reason you want to synchronize on datagram packet
584
// is because you dont want an applet to change the address
585
// while you are trying to send the packet for example
586
// after the security check but before the send.
587
if (security != null) {
588             if (p.getAddress().isMulticastAddress()) {
589             security.checkMulticast(p.getAddress());
590             } else {
591             security.checkConnect(p.getAddress().getHostAddress(),
592                           p.getPort());
593             }
594         }
595         } else {
596         // we're connected
597
packetAddress = p.getAddress();
598         if (packetAddress == null) {
599             p.setAddress(connectedAddress);
600             p.setPort(connectedPort);
601         } else if ((!packetAddress.equals(connectedAddress)) ||
602                p.getPort() != connectedPort) {
603             throw new IllegalArgumentException JavaDoc("connected address " +
604                                "and packet address" +
605                                " differ");
606         }
607         }
608         // Check whether the socket is bound
609
if (!isBound())
610         bind(new InetSocketAddress JavaDoc(0));
611         // call the method to send
612
getImpl().send(p);
613         }
614     }
615
616     /**
617      * Receives a datagram packet from this socket. When this method
618      * returns, the <code>DatagramPacket</code>'s buffer is filled with
619      * the data received. The datagram packet also contains the sender's
620      * IP address, and the port number on the sender's machine.
621      * <p>
622      * This method blocks until a datagram is received. The
623      * <code>length</code> field of the datagram packet object contains
624      * the length of the received message. If the message is longer than
625      * the packet's length, the message is truncated.
626      * <p>
627      * If there is a security manager, a packet cannot be received if the
628      * security manager's <code>checkAccept</code> method
629      * does not allow it.
630      *
631      * @param p the <code>DatagramPacket</code> into which to place
632      * the incoming data.
633      * @exception IOException if an I/O error occurs.
634      * @exception SocketTimeoutException if setSoTimeout was previously called
635      * and the timeout has expired.
636      * @exception PortUnreachableException may be thrown if the socket is connected
637      * to a currently unreachable destination. Note, there is no guarantee that the
638      * exception will be thrown.
639      * @exception java.nio.channels.IllegalBlockingModeException
640      * if this socket has an associated channel,
641      * and the channel is in non-blocking mode.
642      * @see java.net.DatagramPacket
643      * @see java.net.DatagramSocket
644      * @revised 1.4
645      * @spec JSR-51
646      */

647     public synchronized void receive(DatagramPacket JavaDoc p) throws IOException JavaDoc {
648         synchronized (p) {
649         if (!isBound())
650         bind(new InetSocketAddress JavaDoc(0));
651         if (connectState == ST_NOT_CONNECTED) {
652         // check the address is ok with the security manager before every recv.
653
SecurityManager JavaDoc security = System.getSecurityManager();
654         if (security != null) {
655             while(true) {
656             String JavaDoc peekAd = null;
657             int peekPort = 0;
658             // peek at the packet to see who it is from.
659
if (!oldImpl) {
660                 // We can use the new peekData() API
661
DatagramPacket JavaDoc peekPacket = new DatagramPacket JavaDoc(new byte[1], 1);
662                 peekPort = getImpl().peekData(peekPacket);
663                 peekAd = peekPacket.getAddress().getHostAddress();
664             } else {
665                 InetAddress JavaDoc adr = new InetAddress JavaDoc();
666                 peekPort = getImpl().peek(adr);
667                 peekAd = adr.getHostAddress();
668             }
669             try {
670                 security.checkAccept(peekAd, peekPort);
671                 // security check succeeded - so now break
672
// and recv the packet.
673
break;
674             } catch (SecurityException JavaDoc se) {
675                 // Throw away the offending packet by consuming
676
// it in a tmp buffer.
677
DatagramPacket JavaDoc tmp = new DatagramPacket JavaDoc(new byte[1], 1);
678                 getImpl().receive(tmp);
679             
680                 // silently discard the offending packet
681
// and continue: unknown/malicious
682
// entities on nets should not make
683
// runtime throw security exception and
684
// disrupt the applet by sending random
685
// datagram packets.
686
continue;
687             }
688             } // end of while
689
}
690         }
691         if (connectState == ST_CONNECTED_NO_IMPL) {
692         // We have to do the filtering the old fashioned way since
693
// the native impl doesn't support connect or the connect
694
// via the impl failed.
695
boolean stop = false;
696         while (!stop) {
697             // peek at the packet to see who it is from.
698
InetAddress JavaDoc peekAddress = new InetAddress JavaDoc();
699             int peekPort = getImpl().peek(peekAddress);
700             if ((!connectedAddress.equals(peekAddress)) ||
701             (connectedPort != peekPort)) {
702             // throw the packet away and silently continue
703
DatagramPacket JavaDoc tmp = new DatagramPacket JavaDoc(new byte[1], 1);
704             getImpl().receive(tmp);
705             } else {
706             stop = true;
707             }
708         }
709         }
710         // If the security check succeeds, or the datagram is
711
// connected then receive the packet
712
getImpl().receive(p);
713     }
714     }
715
716     /**
717      * Gets the local address to which the socket is bound.
718      *
719      * <p>If there is a security manager, its
720      * <code>checkConnect</code> method is first called
721      * with the host address and <code>-1</code>
722      * as its arguments to see if the operation is allowed.
723      *
724      * @see SecurityManager#checkConnect
725      * @return the local address to which the socket is bound, or
726      * an <code>InetAddress</code> representing any local
727      * address if either the socket is not bound, or
728      * the security manager <code>checkConnect</code>
729      * method does not allow the operation
730      * @since 1.1
731      */

732     public InetAddress JavaDoc getLocalAddress() {
733     if (isClosed())
734         return null;
735     InetAddress JavaDoc in = null;
736     try {
737         in = (InetAddress JavaDoc) getImpl().getOption(SocketOptions.SO_BINDADDR);
738         if (in.isAnyLocalAddress()) {
739         in = InetAddress.anyLocalAddress();
740         }
741         SecurityManager JavaDoc s = System.getSecurityManager();
742         if (s != null) {
743         s.checkConnect(in.getHostAddress(), -1);
744         }
745     } catch (Exception JavaDoc e) {
746         in = InetAddress.anyLocalAddress(); // "0.0.0.0"
747
}
748     return in;
749     }
750
751     /**
752      * Returns the port number on the local host to which this socket is bound.
753      *
754      * @return the port number on the local host to which this socket is bound.
755      */

756     public int getLocalPort() {
757     if (isClosed())
758         return -1;
759     try {
760         return getImpl().getLocalPort();
761     } catch (Exception JavaDoc e) {
762         return 0;
763     }
764     }
765
766     /** Enable/disable SO_TIMEOUT with the specified timeout, in
767      * milliseconds. With this option set to a non-zero timeout,
768      * a call to receive() for this DatagramSocket
769      * will block for only this amount of time. If the timeout expires,
770      * a <B>java.net.SocketTimeoutException</B> is raised, though the
771      * DatagramSocket is still valid. The option <B>must</B> be enabled
772      * prior to entering the blocking operation to have effect. The
773      * timeout must be > 0.
774      * A timeout of zero is interpreted as an infinite timeout.
775      *
776      * @param timeout the specified timeout in milliseconds.
777      * @throws SocketException if there is an error in the underlying protocol, such as an UDP error.
778      * @since JDK1.1
779      * @see #getSoTimeout()
780      */

781     public synchronized void setSoTimeout(int timeout) throws SocketException JavaDoc {
782     if (isClosed())
783         throw new SocketException JavaDoc("Socket is closed");
784     getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer JavaDoc(timeout));
785     }
786
787     /**
788      * Retrieve setting for SO_TIMEOUT. 0 returns implies that the
789      * option is disabled (i.e., timeout of infinity).
790      *
791      * @return the setting for SO_TIMEOUT
792      * @throws SocketException if there is an error in the underlying protocol, such as an UDP error.
793      * @since JDK1.1
794      * @see #setSoTimeout(int)
795      */

796     public synchronized int getSoTimeout() throws SocketException JavaDoc {
797     if (isClosed())
798         throw new SocketException JavaDoc("Socket is closed");
799     if (getImpl() == null)
800         return 0;
801     Object JavaDoc o = getImpl().getOption(SocketOptions.SO_TIMEOUT);
802     /* extra type safety */
803     if (o instanceof Integer JavaDoc) {
804         return ((Integer JavaDoc) o).intValue();
805     } else {
806         return 0;
807     }
808     }
809
810     /**
811      * Sets the SO_SNDBUF option to the specified value for this
812      * <tt>DatagramSocket</tt>. The SO_SNDBUF option is used by the
813      * network implementation as a hint to size the underlying
814      * network I/O buffers. The SO_SNDBUF setting may also be used
815      * by the network implementation to determine the maximum size
816      * of the packet that can be sent on this socket.
817      * <p>
818      * As SO_SNDBUF is a hint, applications that want to verify
819      * what size the buffer is should call {@link #getSendBufferSize()}.
820      * <p>
821      * Increasing the buffer size may allow multiple outgoing packets
822      * to be queued by the network implementation when the send rate
823      * is high.
824      * <p>
825      * Note: If {@link #send(DatagramPacket)} is used to send a
826      * <code>DatagramPacket</code> that is larger than the setting
827      * of SO_SNDBUF then it is implementation specific if the
828      * packet is sent or discarded.
829      *
830      * @param size the size to which to set the send buffer
831      * size. This value must be greater than 0.
832      *
833      * @exception SocketException if there is an error
834      * in the underlying protocol, such as an UDP error.
835      * @exception IllegalArgumentException if the value is 0 or is
836      * negative.
837      * @see #getSendBufferSize()
838      */

839     public synchronized void setSendBufferSize(int size)
840     throws SocketException JavaDoc{
841     if (!(size > 0)) {
842         throw new IllegalArgumentException JavaDoc("negative send size");
843     }
844     if (isClosed())
845         throw new SocketException JavaDoc("Socket is closed");
846     getImpl().setOption(SocketOptions.SO_SNDBUF, new Integer JavaDoc(size));
847     }
848
849     /**
850      * Get value of the SO_SNDBUF option for this <tt>DatagramSocket</tt>, that is the
851      * buffer size used by the platform for output on this <tt>DatagramSocket</tt>.
852      *
853      * @return the value of the SO_SNDBUF option for this <tt>DatagramSocket</tt>
854      * @exception SocketException if there is an error in
855      * the underlying protocol, such as an UDP error.
856      * @see #setSendBufferSize
857      */

858     public synchronized int getSendBufferSize() throws SocketException JavaDoc {
859     if (isClosed())
860         throw new SocketException JavaDoc("Socket is closed");
861     int result = 0;
862     Object JavaDoc o = getImpl().getOption(SocketOptions.SO_SNDBUF);
863     if (o instanceof Integer JavaDoc) {
864         result = ((Integer JavaDoc)o).intValue();
865     }
866     return result;
867     }
868
869     /**
870      * Sets the SO_RCVBUF option to the specified value for this
871      * <tt>DatagramSocket</tt>. The SO_RCVBUF option is used by the
872      * the network implementation as a hint to size the underlying
873      * network I/O buffers. The SO_RCVBUF setting may also be used
874      * by the network implementation to determine the maximum size
875      * of the packet that can be received on this socket.
876      * <p>
877      * Because SO_RCVBUF is a hint, applications that want to
878      * verify what size the buffers were set to should call
879      * {@link #getReceiveBufferSize()}.
880      * <p>
881      * Increasing SO_RCVBUF may allow the network implementation
882