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      * to buffer multiple packets when packets arrive faster than
883      * are being received using {@link #receive(DatagramPacket)}.
884      * <p>
885      * Note: It is implementation specific if a packet larger
886      * than SO_RCVBUF can be received.
887      *
888      * @param size the size to which to set the receive buffer
889      * size. This value must be greater than 0.
890      *
891      * @exception SocketException if there is an error in
892      * the underlying protocol, such as an UDP error.
893      * @exception IllegalArgumentException if the value is 0 or is
894      * negative.
895      * @see #getReceiveBufferSize()
896      */

897     public synchronized void setReceiveBufferSize(int size)
898     throws SocketException JavaDoc{
899     if (size <= 0) {
900         throw new IllegalArgumentException JavaDoc("invalid receive size");
901     }
902     if (isClosed())
903         throw new SocketException JavaDoc("Socket is closed");
904     getImpl().setOption(SocketOptions.SO_RCVBUF, new Integer JavaDoc(size));
905     }
906
907     /**
908      * Get value of the SO_RCVBUF option for this <tt>DatagramSocket</tt>, that is the
909      * buffer size used by the platform for input on this <tt>DatagramSocket</tt>.
910      *
911      * @return the value of the SO_RCVBUF option for this <tt>DatagramSocket</tt>
912      * @exception SocketException if there is an error in the underlying protocol, such as an UDP error.
913      * @see #setReceiveBufferSize(int)
914      */

915     public synchronized int getReceiveBufferSize()
916     throws SocketException JavaDoc{
917     if (isClosed())
918         throw new SocketException JavaDoc("Socket is closed");
919     int result = 0;
920     Object JavaDoc o = getImpl().getOption(SocketOptions.SO_RCVBUF);
921     if (o instanceof Integer JavaDoc) {
922         result = ((Integer JavaDoc)o).intValue();
923     }
924     return result;
925     }
926
927     /**
928      * Enable/disable the SO_REUSEADDR socket option.
929      * <p>
930      * For UDP sockets it may be necessary to bind more than one
931      * socket to the same socket address. This is typically for the
932      * purpose of receiving multicast packets
933      * (See {@link java.net.MulticastSocket}). The
934      * <tt>SO_REUSEADDR</tt> socket option allows multiple
935      * sockets to be bound to the same socket address if the
936      * <tt>SO_REUSEADDR</tt> socket option is enabled prior
937      * to binding the socket using {@link #bind(SocketAddress)}.
938      * <p>
939      * Note: This functionality is not supported by all existing platforms,
940      * so it is implementation specific whether this option will be ignored
941      * or not. However, if it is not supported then
942      * {@link #getReuseAddress()} will always return <code>false</code>.
943      * <p>
944      * When a <tt>DatagramSocket</tt> is created the initial setting
945      * of <tt>SO_REUSEADDR</tt> is disabled.
946      * <p>
947      * The behaviour when <tt>SO_REUSEADDR</tt> is enabled or
948      * disabled after a socket is bound (See {@link #isBound()})
949      * is not defined.
950      *
951      * @param on whether to enable or disable the
952      * @exception SocketException if an error occurs enabling or
953      * disabling the <tt>SO_RESUEADDR</tt> socket option,
954      * or the socket is closed.
955      * @since 1.4
956      * @see #getReuseAddress()
957      * @see #bind(SocketAddress)
958      * @see #isBound()
959      * @see #isClosed()
960      */

961     public synchronized void setReuseAddress(boolean on) throws SocketException JavaDoc {
962     if (isClosed())
963         throw new SocketException JavaDoc("Socket is closed");
964     // Integer instead of Boolean for compatibility with older DatagramSocketImpl
965
if (oldImpl)
966         getImpl().setOption(SocketOptions.SO_REUSEADDR, new Integer JavaDoc(on?-1:0));
967     else
968         getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on));
969     }
970
971     /**
972      * Tests if SO_REUSEADDR is enabled.
973      *
974      * @return a <code>boolean</code> indicating whether or not SO_REUSEADDR is enabled.
975      * @exception SocketException if there is an error
976      * in the underlying protocol, such as an UDP error.
977      * @since 1.4
978      * @see #setReuseAddress(boolean)
979      */

980     public synchronized boolean getReuseAddress() throws SocketException JavaDoc {
981     if (isClosed())
982         throw new SocketException JavaDoc("Socket is closed");
983     Object JavaDoc o = getImpl().getOption(SocketOptions.SO_REUSEADDR);
984     return ((Boolean JavaDoc)o).booleanValue();
985     }
986
987     /**
988      * Enable/disable SO_BROADCAST.
989      * @param on whether or not to have broadcast turned on.
990      * @exception SocketException if there is an error
991      * in the underlying protocol, such as an UDP error.
992      * @since 1.4
993      * @see #getBroadcast()
994      */

995     public synchronized void setBroadcast(boolean on) throws SocketException JavaDoc {
996     if (isClosed())
997         throw new SocketException JavaDoc("Socket is closed");
998         getImpl().setOption(SocketOptions.SO_BROADCAST, Boolean.valueOf(on));
999     }
1000
1001    /**
1002     * Tests if SO_BROADCAST is enabled.
1003     * @return a <code>boolean</code> indicating whether or not SO_BROADCAST is enabled.
1004     * @exception SocketException if there is an error
1005     * in the underlying protocol, such as an UDP error.
1006     * @since 1.4
1007     * @see #setBroadcast(boolean)
1008     */

1009    public synchronized boolean getBroadcast() throws SocketException JavaDoc {
1010    if (isClosed())
1011        throw new SocketException JavaDoc("Socket is closed");
1012        return ((Boolean JavaDoc)(getImpl().getOption(SocketOptions.SO_BROADCAST))).booleanValue();
1013    }
1014
1015    /**
1016     * Sets traffic class or type-of-service octet in the IP
1017     * datagram header for datagrams sent from this DatagramSocket.
1018     * As the underlying network implementation may ignore this
1019     * value applications should consider it a hint.
1020     *
1021     * <P> The tc <B>must</B> be in the range <code> 0 <= tc <=
1022     * 255</code> or an IllegalArgumentException will be thrown.
1023     * <p>Notes:
1024     * <p> for Internet Protocol v4 the value consists of an octet
1025     * with precedence and TOS fields as detailed in RFC 1349. The
1026     * TOS field is bitset created by bitwise-or'ing values such
1027     * the following :-
1028     * <p>
1029     * <UL>
1030     * <LI><CODE>IPTOS_LOWCOST (0x02)</CODE></LI>
1031     * <LI><CODE>IPTOS_RELIABILITY (0x04)</CODE></LI>
1032     * <LI><CODE>IPTOS_THROUGHPUT (0x08)</CODE></LI>
1033     * <LI><CODE>IPTOS_LOWDELAY (0x10)</CODE></LI>
1034     * </UL>
1035     * The last low order bit is always ignored as this
1036     * corresponds to the MBZ (must be zero) bit.
1037     * <p>
1038     * Setting bits in the precedence field may result in a
1039     * SocketException indicating that the operation is not
1040     * permitted.
1041     * <p>
1042     * for Internet Protocol v6 <code>tc</code> is the value that
1043     * would be placed into the sin6_flowinfo field of the IP header.
1044     *
1045     * @param tc an <code>int</code> value for the bitset.
1046     * @throws SocketException if there is an error setting the
1047     * traffic class or type-of-service
1048     * @since 1.4
1049     * @see #getTrafficClass
1050     */

1051    public synchronized void setTrafficClass(int tc) throws SocketException JavaDoc {
1052    if (tc < 0 || tc > 255)
1053        throw new IllegalArgumentException JavaDoc("tc is not in range 0 -- 255");
1054
1055    if (isClosed())
1056        throw new SocketException JavaDoc("Socket is closed");
1057        getImpl().setOption(SocketOptions.IP_TOS, new Integer JavaDoc(tc));
1058    }
1059
1060    /**
1061     * Gets traffic class or type-of-service in the IP datagram
1062     * header for packets sent from this DatagramSocket.
1063     * <p>
1064     * As the underlying network implementation may ignore the
1065     * traffic class or type-of-service set using {@link #setTrafficClass(int)}
1066     * this method may return a different value than was previously
1067     * set using the {@link #setTrafficClass(int)} method on this
1068     * DatagramSocket.
1069     *
1070     * @return the traffic class or type-of-service already set
1071     * @throws SocketException if there is an error obtaining the
1072     * traffic class or type-of-service value.
1073     * @since 1.4
1074     * @see #setTrafficClass(int)
1075     */

1076    public synchronized int getTrafficClass() throws SocketException JavaDoc {
1077    if (isClosed())
1078        throw new SocketException JavaDoc("Socket is closed");
1079        return ((Integer JavaDoc)(getImpl().getOption(SocketOptions.IP_TOS))).intValue();
1080    }
1081
1082    /**
1083     * Closes this datagram socket.
1084     * <p>
1085     * Any thread currently blocked in {@link #receive} upon this socket
1086     * will throw a {@link SocketException}.
1087     *
1088     * <p> If this socket has an associated channel then the channel is closed
1089     * as well.
1090     *
1091     * @revised 1.4
1092     * @spec JSR-51
1093     */

1094    public void close() {
1095    synchronized(closeLock) {
1096        if (isClosed())
1097        return;
1098        impl.close();
1099        closed = true;
1100    }
1101    }
1102 
1103    /**
1104     * Returns whether the socket is closed or not.
1105     *
1106     * @return true if the socket has been closed
1107     * @since 1.4
1108     */

1109    public boolean isClosed() {
1110    synchronized(closeLock) {
1111        return closed;
1112    }
1113    }
1114
1115    /**
1116     * Returns the unique {@link java.nio.channels.DatagramChannel} object
1117     * associated with this datagram socket, if any.
1118     *
1119     * <p> A datagram socket will have a channel if, and only if, the channel
1120     * itself was created via the {@link java.nio.channels.DatagramChannel#open
1121     * DatagramChannel.open} method.
1122     *
1123     * @return the datagram channel associated with this datagram socket,
1124     * or <tt>null</tt> if this socket was not created for a channel
1125     *
1126     * @since 1.4
1127     * @spec JSR-51
1128     */

1129    public DatagramChannel JavaDoc getChannel() {
1130    return null;
1131    }
1132
1133    /**
1134     * The factory for all datagram sockets.
1135     */

1136    static DatagramSocketImplFactory JavaDoc factory;
1137 
1138    /**
1139     * Sets the datagram socket implementation factory for the
1140     * application. The factory can be specified only once.
1141     * <p>
1142     * When an application creates a new datagram socket, the socket
1143     * implementation factory's <code>createDatagramSocketImpl</code> method is
1144     * called to create the actual datagram socket implementation.
1145     * <p>
1146     * Passing <code>null</code> to the method is a no-op unless the factory
1147     * was already set.
1148     *
1149     * <p>If there is a security manager, this method first calls
1150     * the security manager's <code>checkSetFactory</code> method
1151     * to ensure the operation is allowed.
1152     * This could result in a SecurityException.
1153     *
1154     * @param fac the desired factory.
1155     * @exception IOException if an I/O error occurs when setting the
1156     * datagram socket factory.
1157     * @exception SocketException if the factory is already defined.
1158     * @exception SecurityException if a security manager exists and its
1159     * <code>checkSetFactory</code> method doesn't allow the
1160     operation.
1161     * @see
1162     java.net.DatagramSocketImplFactory#createDatagramSocketImpl()
1163     * @see SecurityManager#checkSetFactory
1164     * @since 1.3
1165     */

1166    public static synchronized void
1167    setDatagramSocketImplFactory(DatagramSocketImplFactory JavaDoc fac)
1168       throws IOException JavaDoc
1169    {
1170        if (factory != null) {
1171        throw new SocketException JavaDoc("factory already defined");
1172    }
1173    SecurityManager JavaDoc security = System.getSecurityManager();
1174    if (security != null) {
1175        security.checkSetFactory();
1176    }
1177    factory = fac;
1178    }
1179}
1180
Popular Tags