1 /* DatagramSocket.java -- A class to model UDP sockets
2 Copyright (C) 1998, 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
41 import gnu
.java
.net
.PlainDatagramSocketImpl
;
42 import java
.io
.IOException
;
43 import java
.nio
.channels
.DatagramChannel
;
44 import java
.nio
.channels
.IllegalBlockingModeException
;
47 * Written using on-line Java Platform 1.2 API Specification, as well
48 * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
49 * Status: Believed complete and correct.
53 * This class models a connectionless datagram socket that sends
54 * individual packets of data across the network. In the TCP/IP world,
55 * this means UDP. Datagram packets do not have guaranteed delivery,
56 * or any guarantee about the order the data will be received on the
59 * @author Aaron M. Renn (arenn@urbanophile.com)
60 * @author Warren Levy (warrenl@cygnus.com)
64 public class DatagramSocket
67 * This is the user DatagramSocketImplFactory for this class. If this
68 * variable is null, a default factory is used.
70 private static DatagramSocketImplFactory factory
;
73 * This is the implementation object used by this socket.
75 private DatagramSocketImpl impl
;
78 * True if socket implementation was created.
80 private boolean implCreated
;
83 * This is the address we are "connected" to
85 private InetAddress remoteAddress
;
88 * This is the port we are "connected" to
90 private int remotePort
= -1;
93 * True if socket is bound.
95 private boolean bound
;
98 * Creates a <code>DatagramSocket</code> from a specified
99 * <code>DatagramSocketImpl</code> instance
101 * @param impl The <code>DatagramSocketImpl</code> the socket will be
106 protected DatagramSocket (DatagramSocketImpl impl
)
109 throw new NullPointerException("impl may not be null");
112 this.remoteAddress
= null;
113 this.remotePort
= -1;
117 * Initializes a new instance of <code>DatagramSocket</code> that binds to
118 * a random port and every address on the local machine.
120 * @exception SocketException If an error occurs.
121 * @exception SecurityException If a security manager exists and
122 * its <code>checkListen</code> method doesn't allow the operation.
124 public DatagramSocket() throws SocketException
126 this(new InetSocketAddress(0));
130 * Initializes a new instance of <code>DatagramSocket</code> that binds to
131 * the specified port and every address on the local machine.
133 * @param port The local port number to bind to.
135 * @exception SecurityException If a security manager exists and its
136 * <code>checkListen</code> method doesn't allow the operation.
137 * @exception SocketException If an error occurs.
139 public DatagramSocket(int port
) throws SocketException
141 this(new InetSocketAddress(port
));
145 * Initializes a new instance of <code>DatagramSocket</code> that binds to
146 * the specified local port and address.
148 * @param port The local port number to bind to.
149 * @param addr The local address to bind to.
151 * @exception SecurityException If a security manager exists and its
152 * checkListen method doesn't allow the operation.
153 * @exception SocketException If an error occurs.
155 public DatagramSocket(int port
, InetAddress addr
) throws SocketException
157 this(new InetSocketAddress(addr
, port
));
161 * Initializes a new instance of <code>DatagramSocket</code> that binds to
162 * the specified local port and address.
164 * @param address The local address and port number to bind to.
166 * @exception SecurityException If a security manager exists and its
167 * <code>checkListen</code> method doesn't allow the operation.
168 * @exception SocketException If an error occurs.
172 public DatagramSocket (SocketAddress address
) throws SocketException
174 String propVal
= System
.getProperty("impl.prefix");
175 if (propVal
== null || propVal
.equals(""))
176 impl
= new PlainDatagramSocketImpl();
180 impl
= (DatagramSocketImpl
) Class
.forName
181 ("java.net." + propVal
+ "DatagramSocketImpl").newInstance();
185 System
.err
.println("Could not instantiate class: java.net." +
186 propVal
+ "DatagramSocketImpl");
187 impl
= new PlainDatagramSocketImpl();
194 // This needs to be accessible from java.net.MulticastSocket
195 DatagramSocketImpl
getImpl()
196 throws SocketException
208 catch (IOException e
)
210 throw new SocketException(e
.getMessage());
215 * Closes this datagram socket.
226 catch (SocketException e
)
228 // Ignore this case, just close the socket in finally clause.
232 remoteAddress
= null;
239 if (getChannel() != null)
240 getChannel().close();
242 catch (IOException e
)
249 * This method returns the remote address to which this socket is
250 * connected. If this socket is not connected, then this method will
251 * return <code>null</code>.
253 * @return The remote address.
257 public InetAddress
getInetAddress()
259 return remoteAddress
;
263 * This method returns the remote port to which this socket is
264 * connected. If this socket is not connected, then this method will
267 * @return The remote port.
277 * Returns the local address this datagram socket is bound to.
279 * @return The local address is the socket is bound or null
283 public InetAddress
getLocalAddress()
288 InetAddress localAddr
;
292 localAddr
= (InetAddress
) getImpl().getOption(SocketOptions
.SO_BINDADDR
);
294 SecurityManager s
= System
.getSecurityManager();
296 s
.checkConnect (localAddr
.getHostName(), -1);
298 catch (SecurityException e
)
300 localAddr
= InetAddress
.ANY_IF
;
302 catch (SocketException e
)
304 // This cannot happen as we are bound.
312 * Returns the local port this socket is bound to.
314 * @return The local port number.
316 public int getLocalPort()
323 return getImpl().getLocalPort();
325 catch (SocketException e
)
327 // This cannot happen as we are bound.
333 * Returns the value of the socket's SO_TIMEOUT setting. If this method
334 * returns 0 then SO_TIMEOUT is disabled.
336 * @return The current timeout in milliseconds.
338 * @exception SocketException If an error occurs.
342 public synchronized int getSoTimeout() throws SocketException
345 throw new SocketException("socket is closed");
347 Object buf
= getImpl().getOption(SocketOptions
.SO_TIMEOUT
);
349 if (buf
instanceof Integer
)
350 return ((Integer
) buf
).intValue();
352 throw new SocketException("unexpected type");
356 * Sets the value of the socket's SO_TIMEOUT value. A value of 0 will
357 * disable SO_TIMEOUT. Any other value is the number of milliseconds
358 * a socket read/write will block before timing out.
360 * @param timeout The new SO_TIMEOUT value in milliseconds.
362 * @exception SocketException If an error occurs.
366 public synchronized void setSoTimeout(int timeout
) throws SocketException
369 throw new SocketException("socket is closed");
372 throw new IllegalArgumentException("Invalid timeout: " + timeout
);
374 getImpl().setOption(SocketOptions
.SO_TIMEOUT
, new Integer(timeout
));
378 * This method returns the value of the system level socket option
379 * SO_SNDBUF, which is used by the operating system to tune buffer
380 * sizes for data transfers.
382 * @return The send buffer size.
384 * @exception SocketException If an error occurs.
388 public int getSendBufferSize() throws SocketException
391 throw new SocketException("socket is closed");
393 Object buf
= getImpl().getOption(SocketOptions
.SO_SNDBUF
);
395 if (buf
instanceof Integer
)
396 return ((Integer
) buf
).intValue();
398 throw new SocketException("unexpected type");
402 * This method sets the value for the system level socket option
403 * SO_SNDBUF to the specified value. Note that valid values for this
404 * option are specific to a given operating system.
406 * @param size The new send buffer size.
408 * @exception SocketException If an error occurs.
409 * @exception IllegalArgumentException If size is 0 or negative.
413 public void setSendBufferSize(int size
) throws SocketException
416 throw new SocketException("socket is closed");
419 throw new IllegalArgumentException("Buffer size is less than 0");
421 getImpl().setOption(SocketOptions
.SO_SNDBUF
, new Integer(size
));
425 * This method returns the value of the system level socket option
426 * SO_RCVBUF, which is used by the operating system to tune buffer
427 * sizes for data transfers.
429 * @return The receive buffer size.
431 * @exception SocketException If an error occurs.
435 public int getReceiveBufferSize() throws SocketException
438 throw new SocketException("socket is closed");
440 Object buf
= getImpl().getOption(SocketOptions
.SO_RCVBUF
);
442 if (buf
instanceof Integer
)
443 return ((Integer
) buf
).intValue();
445 throw new SocketException("unexpected type");
449 * This method sets the value for the system level socket option
450 * SO_RCVBUF to the specified value. Note that valid values for this
451 * option are specific to a given operating system.
453 * @param size The new receive buffer size.
455 * @exception SocketException If an error occurs.
456 * @exception IllegalArgumentException If size is 0 or negative.
460 public void setReceiveBufferSize(int size
) throws SocketException
463 throw new SocketException("socket is closed");
466 throw new IllegalArgumentException("Buffer size is less than 0");
468 getImpl().setOption(SocketOptions
.SO_RCVBUF
, new Integer(size
));
472 * This method connects this socket to the specified address and port.
473 * When a datagram socket is connected, it will only send or receive
474 * packets to and from the host to which it is connected. A multicast
475 * socket that is connected may only send and not receive packets.
477 * @param address The address to connect this socket to.
478 * @param port The port to connect this socket to.
480 * @exception SocketException If an error occurs.
481 * @exception IllegalArgumentException If address or port are invalid.
482 * @exception SecurityException If the caller is not allowed to send
483 * datagrams to or receive from this address and port.
487 public void connect(InetAddress address
, int port
)
490 throw new IllegalArgumentException ("Connect address may not be null");
492 if ((port
< 1) || (port
> 65535))
493 throw new IllegalArgumentException ("Port number is illegal: " + port
);
495 SecurityManager sm
= System
.getSecurityManager();
497 sm
.checkConnect(address
.getHostName(), port
);
501 getImpl().connect (address
, port
);
502 remoteAddress
= address
;
505 catch (SocketException e
)
507 // This means simply not connected or connect not implemented.
512 * This method disconnects this socket from the address/port it was
513 * connected to. If the socket was not connected in the first place,
514 * this method does nothing.
518 public void disconnect()
525 getImpl().disconnect();
527 catch (SocketException e
)
529 // This cannot happen as we are connected.
533 remoteAddress
= null;
539 * Reads a datagram packet from the socket. Note that this method
540 * will block until a packet is received from the network. On return,
541 * the passed in <code>DatagramPacket</code> is populated with the data
542 * received and all the other information about the packet.
544 * @param p A <code>DatagramPacket</code> for storing the data
546 * @exception IOException If an error occurs.
547 * @exception SocketTimeoutException If setSoTimeout was previously called
548 * and the timeout has expired.
549 * @exception PortUnreachableException If the socket is connected to a
550 * currently unreachable destination. Note, there is no guarantee that the
551 * exception will be thrown.
552 * @exception IllegalBlockingModeException If this socket has an associated
553 * channel, and the channel is in non-blocking mode.
554 * @exception SecurityException If a security manager exists and its
555 * checkAccept ethod doesn't allow the receive.
557 public synchronized void receive(DatagramPacket p
) throws IOException
560 throw new SocketException("socket is closed");
562 if (remoteAddress
!= null
563 && remoteAddress
.isMulticastAddress())
564 throw new IOException
565 ("Socket connected to a multicast address my not receive");
567 if (getChannel() != null
568 && !getChannel().isBlocking ())
569 throw new IllegalBlockingModeException ();
571 getImpl().receive(p
);
573 SecurityManager s
= System
.getSecurityManager();
574 if (s
!= null && isConnected ())
575 s
.checkAccept (p
.getAddress().getHostName (), p
.getPort ());
579 * Sends the specified packet. The host and port to which the packet
580 * are to be sent should be set inside the packet.
582 * @param p The datagram packet to send.
584 * @exception IOException If an error occurs.
585 * @exception SecurityException If a security manager exists and its
586 * checkMulticast or checkConnect method doesn't allow the send.
587 * @exception PortUnreachableException If the socket is connected to a
588 * currently unreachable destination. Note, there is no guarantee that the
589 * exception will be thrown.
590 * @exception IllegalBlockingModeException If this socket has an associated
591 * channel, and the channel is in non-blocking mode.
593 public void send(DatagramPacket p
) throws IOException
596 throw new SocketException("socket is closed");
598 // JDK1.2: Don't do security checks if socket is connected; see jdk1.2 api.
599 SecurityManager s
= System
.getSecurityManager();
600 if (s
!= null && !isConnected ())
602 InetAddress addr
= p
.getAddress();
603 if (addr
.isMulticastAddress())
604 s
.checkMulticast(addr
);
606 s
.checkConnect(addr
.getHostAddress(), p
.getPort());
611 if (p
.getAddress () != null && (remoteAddress
!= p
.getAddress () ||
612 remotePort
!= p
.getPort ()))
613 throw new IllegalArgumentException (
614 "DatagramPacket address does not match remote address" );
617 // FIXME: if this is a subclass of MulticastSocket,
618 // use getTimeToLive for TTL val.
620 if (getChannel() != null
621 && !getChannel().isBlocking ())
622 throw new IllegalBlockingModeException ();
628 * Binds the socket to the given socket address.
630 * @param address The socket address to bind to.
632 * @exception SocketException If an error occurs.
633 * @exception SecurityException If a security manager exists and
634 * its checkListen method doesn't allow the operation.
635 * @exception IllegalArgumentException If address type is not supported.
639 public void bind (SocketAddress address
)
640 throws SocketException
643 throw new SocketException("socket is closed");
645 if (! (address
instanceof InetSocketAddress
))
646 throw new IllegalArgumentException("unsupported address type");
648 InetAddress addr
= ((InetSocketAddress
) address
).getAddress();
649 int port
= ((InetSocketAddress
) address
).getPort();
651 if (port
< 0 || port
> 65535)
652 throw new IllegalArgumentException("Invalid port: " + port
);
654 SecurityManager s
= System
.getSecurityManager ();
659 addr
= InetAddress
.ANY_IF
;
663 getImpl().bind(port
, addr
);
666 catch (SocketException exception
)
671 catch (RuntimeException exception
)
684 * Checks if the datagram socket is closed.
686 * @return True if socket is closed, false otherwise.
690 public boolean isClosed()
696 * Returns the datagram channel assoziated with this datagram socket.
698 * @return The associated <code>DatagramChannel</code> object or null
702 public DatagramChannel
getChannel()
708 * Connects the datagram socket to a specified socket address.
710 * @param address The socket address to connect to.
712 * @exception SocketException If an error occurs.
713 * @exception IllegalArgumentException If address type is not supported.
717 public void connect (SocketAddress address
) throws SocketException
720 throw new SocketException("socket is closed");
722 if ( !(address
instanceof InetSocketAddress
) )
723 throw new IllegalArgumentException("unsupported address type");
725 InetSocketAddress tmp
= (InetSocketAddress
) address
;
726 connect(tmp
.getAddress(), tmp
.getPort());
730 * Returns the binding state of the socket.
732 * @return True if socket bound, false otherwise.
736 public boolean isBound()
742 * Returns the connection state of the socket.
744 * @return True if socket is connected, false otherwise.
748 public boolean isConnected()
750 return remoteAddress
!= null;
754 * Returns the SocketAddress of the host this socket is conneted to
755 * or null if this socket is not connected.
757 * @return The socket address of the remote host if connected or null
761 public SocketAddress
getRemoteSocketAddress()
766 return new InetSocketAddress (remoteAddress
, remotePort
);
770 * Returns the local SocketAddress this socket is bound to.
772 * @return The local SocketAddress or null if the socket is not bound.
776 public SocketAddress
getLocalSocketAddress()
781 return new InetSocketAddress (getLocalAddress(), getLocalPort());
785 * Enables/Disables SO_REUSEADDR.
787 * @param on Whether or not to have SO_REUSEADDR turned on.
789 * @exception SocketException If an error occurs.
793 public void setReuseAddress(boolean on
) throws SocketException
796 throw new SocketException("socket is closed");
798 getImpl().setOption (SocketOptions
.SO_REUSEADDR
, new Boolean (on
));
802 * Checks if SO_REUSEADDR is enabled.
804 * @return True if SO_REUSEADDR is set on the socket, false otherwise.
806 * @exception SocketException If an error occurs.
810 public boolean getReuseAddress() throws SocketException
813 throw new SocketException("socket is closed");
815 Object buf
= getImpl().getOption (SocketOptions
.SO_REUSEADDR
);
817 if (buf
instanceof Boolean
)
818 return ((Boolean
) buf
).booleanValue();
820 throw new SocketException("unexpected type");
824 * Enables/Disables SO_BROADCAST
826 * @param enable True if SO_BROADCAST should be enabled, false otherwise.
828 * @exception SocketException If an error occurs
832 public void setBroadcast(boolean enable
) throws SocketException
835 throw new SocketException("socket is closed");
837 getImpl().setOption(SocketOptions
.SO_BROADCAST
, new Boolean(enable
));
841 * Checks if SO_BROADCAST is enabled
843 * @return Whether SO_BROADCAST is set
845 * @exception SocketException If an error occurs
849 public boolean getBroadcast() throws SocketException
852 throw new SocketException("socket is closed");
854 Object buf
= getImpl().getOption(SocketOptions
.SO_BROADCAST
);
856 if (buf
instanceof Boolean
)
857 return ((Boolean
) buf
).booleanValue();
859 throw new SocketException("unexpected type");
863 * Sets the traffic class value
865 * @param tc The traffic class
867 * @exception SocketException If an error occurs
868 * @exception IllegalArgumentException If tc value is illegal
870 * @see DatagramSocket#getTrafficClass()
874 public void setTrafficClass(int tc
)
875 throws SocketException
878 throw new SocketException("socket is closed");
880 if (tc
< 0 || tc
> 255)
881 throw new IllegalArgumentException();
883 getImpl().setOption (SocketOptions
.IP_TOS
, new Integer (tc
));
887 * Returns the current traffic class
889 * @return The current traffic class.
891 * @see DatagramSocket#setTrafficClass(int tc)
893 * @exception SocketException If an error occurs
897 public int getTrafficClass() throws SocketException
900 throw new SocketException("socket is closed");
902 Object buf
= getImpl().getOption(SocketOptions
.IP_TOS
);
904 if (buf
instanceof Integer
)
905 return ((Integer
) buf
).intValue();
907 throw new SocketException("unexpected type");
911 * Sets the datagram socket implementation factory for the application
913 * @param fac The factory to set
915 * @exception IOException If an error occurs
916 * @exception SocketException If the factory is already defined
917 * @exception SecurityException If a security manager exists and its
918 * checkSetFactory method doesn't allow the operation
920 public static void setDatagramSocketImplFactory
921 (DatagramSocketImplFactory fac
) throws IOException
924 throw new SocketException ("DatagramSocketImplFactory already defined");
926 SecurityManager sm
= System
.getSecurityManager();
928 sm
.checkSetFactory();