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 static DatagramSocketImplFactory factory;
73 * This is the implementation object used by this socket.
75 DatagramSocketImpl impl;
78 * The unique DatagramChannel object associated with this datagram socket,
84 * This is the address we are "connected" to
86 private InetAddress remoteAddress;
89 * This is the port we are "connected" to
91 private int remotePort = -1;
94 * Indicates when the socket is closed.
96 private boolean closed = false;
99 * Creates a <code>DatagramSocket</code> from a specified
100 * <code>DatagramSocketImpl</code> instance
102 * @param impl The <code>DatagramSocketImpl</code> the socket will be
107 protected DatagramSocket (DatagramSocketImpl impl)
110 this.remoteAddress = null;
111 this.remotePort = -1;
115 * Initializes a new instance of <code>DatagramSocket</code> that binds to
116 * a random port and every address on the local machine.
118 * @exception SocketException If an error occurs.
119 * @exception SecurityException If a security manager exists and
120 * its <code>checkListen</code> method doesn't allow the operation.
122 public DatagramSocket() throws SocketException
128 * Initializes a new instance of <code>DatagramSocket</code> that binds to
129 * the specified port and every address on the local machine.
131 * @param port The local port number to bind to.
133 * @exception SecurityException If a security manager exists and its
134 * <code>checkListen</code> method doesn't allow the operation.
135 * @exception SocketException If an error occurs.
137 public DatagramSocket(int port) throws SocketException
143 * Initializes a new instance of <code>DatagramSocket</code> that binds to
144 * the specified local port and address.
146 * @param port The local port number to bind to.
147 * @param laddr The local address to bind to.
149 * @exception SecurityException If a security manager exists and its
150 * checkListen method doesn't allow the operation.
151 * @exception SocketException If an error occurs.
153 public DatagramSocket(int port, InetAddress laddr) throws SocketException
155 if (port < 0 || port > 65535)
156 throw new IllegalArgumentException("Invalid port: " + port);
158 SecurityManager s = System.getSecurityManager();
162 String propVal = System.getProperty("impl.prefix");
163 if (propVal == null || propVal.equals(""))
164 impl = new PlainDatagramSocketImpl();
168 impl = (DatagramSocketImpl) Class.forName
169 ("java.net." + propVal + "DatagramSocketImpl").newInstance();
173 System.err.println("Could not instantiate class: java.net." +
174 propVal + "DatagramSocketImpl");
175 impl = new PlainDatagramSocketImpl();
180 laddr = InetAddress.ANY_IF;
184 impl.bind (port, laddr);
186 catch (SocketException exception)
191 catch (RuntimeException exception)
204 * Initializes a new instance of <code>DatagramSocket</code> that binds to
205 * the specified local port and address.
207 * @param port The local port number to bind to.
208 * @param laddr The local address to bind to.
210 * @exception SecurityException If a security manager exists and its
211 * <code>checkListen</code> method doesn't allow the operation.
212 * @exception SocketException If an error occurs.
216 public DatagramSocket (SocketAddress address) throws SocketException
218 this (((InetSocketAddress) address).getPort (),
219 ((InetSocketAddress) address).getAddress ());
223 * Closes this datagram socket.
230 remoteAddress = null;
237 * This method returns the remote address to which this socket is
238 * connected. If this socket is not connected, then this method will
239 * return <code>null</code>.
241 * @return The remote address.
245 public InetAddress getInetAddress()
247 return remoteAddress;
251 * This method returns the remote port to which this socket is
252 * connected. If this socket is not connected, then this method will
255 * @return The remote port.
265 * Returns the local address this datagram socket is bound to.
269 public InetAddress getLocalAddress()
279 result = (InetAddress) impl.getOption (SocketOptions.SO_BINDADDR);
281 SecurityManager s = System.getSecurityManager();
283 s.checkConnect (result.getHostName(), -1);
285 catch (SecurityException e)
287 result = InetAddress.ANY_IF;
289 catch (SocketException e)
291 result = InetAddress.ANY_IF;
298 * Returns the local port this socket is bound to.
300 * @return The local port number.
302 public int getLocalPort()
304 return impl.getLocalPort();
308 * Returns the value of the socket's SO_TIMEOUT setting. If this method
309 * returns 0 then SO_TIMEOUT is disabled.
311 * @return The current timeout in milliseconds.
313 * @exception SocketException If an error occurs.
317 public synchronized int getSoTimeout() throws SocketException
320 throw new SocketException ("Cannot initialize Socket implementation");
322 Object timeout = impl.getOption(SocketOptions.SO_TIMEOUT);
324 if (timeout instanceof Integer)
325 return ((Integer)timeout).intValue();
331 * Sets the value of the socket's SO_TIMEOUT value. A value of 0 will
332 * disable SO_TIMEOUT. Any other value is the number of milliseconds
333 * a socket read/write will block before timing out.
335 * @param timeout The new SO_TIMEOUT value in milliseconds.
337 * @exception SocketException If an error occurs.
341 public synchronized void setSoTimeout(int timeout) throws SocketException
344 throw new IllegalArgumentException("Invalid timeout: " + timeout);
346 impl.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
350 * This method returns the value of the system level socket option
351 * SO_SNDBUF, which is used by the operating system to tune buffer
352 * sizes for data transfers.
354 * @return The send buffer size.
356 * @exception SocketException If an error occurs.
360 public int getSendBufferSize() throws SocketException
363 throw new SocketException ("Cannot initialize Socket implementation");
365 Object obj = impl.getOption(SocketOptions.SO_SNDBUF);
367 if (obj instanceof Integer)
368 return(((Integer)obj).intValue());
370 throw new SocketException("Unexpected type");
374 * This method sets the value for the system level socket option
375 * SO_SNDBUF to the specified value. Note that valid values for this
376 * option are specific to a given operating system.
378 * @param size The new send buffer size.
380 * @exception SocketException If an error occurs.
381 * @exception IllegalArgumentException If size is 0 or negative.
385 public void setSendBufferSize(int size) throws SocketException
388 throw new IllegalArgumentException("Buffer size is less than 0");
390 impl.setOption(SocketOptions.SO_SNDBUF, new Integer(size));
394 * This method returns the value of the system level socket option
395 * SO_RCVBUF, which is used by the operating system to tune buffer
396 * sizes for data transfers.
398 * @return The receive buffer size.
400 * @exception SocketException If an error occurs.
404 public int getReceiveBufferSize() throws SocketException
407 throw new SocketException ("Cannot initialize Socket implementation");
409 Object obj = impl.getOption(SocketOptions.SO_RCVBUF);
411 if (obj instanceof Integer)
412 return(((Integer)obj).intValue());
414 throw new SocketException("Unexpected type");
418 * This method sets the value for the system level socket option
419 * SO_RCVBUF to the specified value. Note that valid values for this
420 * option are specific to a given operating system.
422 * @param size The new receive buffer size.
424 * @exception SocketException If an error occurs.
425 * @exception IllegalArgumentException If size is 0 or negative.
429 public void setReceiveBufferSize(int size) throws SocketException
432 throw new SocketException ("Cannot initialize Socket implementation");
435 throw new IllegalArgumentException("Buffer size is less than 0");
437 impl.setOption(SocketOptions.SO_RCVBUF, new Integer(size));
441 * This method connects this socket to the specified address and port.
442 * When a datagram socket is connected, it will only send or receive
443 * packets to and from the host to which it is connected. A multicast
444 * socket that is connected may only send and not receive packets.
446 * @param address The address to connect this socket to.
447 * @param port The port to connect this socket to.
449 * @exception SocketException If an error occurs.
450 * @exception IllegalArgumentException If address or port are invalid.
451 * @exception SecurityException If the caller is not allowed to send
452 * datagrams to or receive from this address and port.
456 public void connect(InetAddress address, int port)
459 throw new IllegalArgumentException ("Connect address may not be null");
461 if ((port < 1) || (port > 65535))
462 throw new IllegalArgumentException ("Port number is illegal: " + port);
464 SecurityManager sm = System.getSecurityManager();
466 sm.checkConnect(address.getHostName(), port);
470 impl.connect (address, port);
471 remoteAddress = address;
474 catch (SocketException e)
476 // This means simply not connected or connect not implemented.
481 * This method disconnects this socket from the address/port it was
482 * connected to. If the socket was not connected in the first place,
483 * this method does nothing.
487 public void disconnect()
490 remoteAddress = null;
495 * Reads a datagram packet from the socket. Note that this method
496 * will block until a packet is received from the network. On return,
497 * the passed in <code>DatagramPacket</code> is populated with the data
498 * received and all the other information about the packet.
500 * @param p A <code>DatagramPacket</code> for storing the data
502 * @exception IOException If an error occurs.
503 * @exception SocketTimeoutException If setSoTimeout was previously called
504 * and the timeout has expired.
505 * @exception PortUnreachableException If the socket is connected to a
506 * currently unreachable destination. Note, there is no guarantee that the
507 * exception will be thrown.
508 * @exception IllegalBlockingModeException If this socket has an associated
509 * channel, and the channel is in non-blocking mode.
510 * @exception SecurityException If a security manager exists and its
511 * checkAccept ethod doesn't allow the receive.
513 public synchronized void receive(DatagramPacket p) throws IOException
516 throw new IOException ("Cannot initialize Socket implementation");
518 if (remoteAddress != null && remoteAddress.isMulticastAddress ())
519 throw new IOException (
520 "Socket connected to a multicast address my not receive");
522 if (ch != null && !ch.isBlocking ())
523 throw new IllegalBlockingModeException ();
527 SecurityManager s = System.getSecurityManager();
528 if (s != null && isConnected ())
529 s.checkAccept (p.getAddress().getHostName (), p.getPort ());
533 * Sends the specified packet. The host and port to which the packet
534 * are to be sent should be set inside the packet.
536 * @param p The datagram packet to send.
538 * @exception IOException If an error occurs.
539 * @exception SecurityException If a security manager exists and its
540 * checkMulticast or checkConnect method doesn't allow the send.
541 * @exception PortUnreachableException If the socket is connected to a
542 * currently unreachable destination. Note, there is no guarantee that the
543 * exception will be thrown.
544 * @exception IllegalBlockingModeException If this socket has an associated
545 * channel, and the channel is in non-blocking mode.
547 public void send(DatagramPacket p) throws IOException
549 // JDK1.2: Don't do security checks if socket is connected; see jdk1.2 api.
550 SecurityManager s = System.getSecurityManager();
551 if (s != null && !isConnected ())
553 InetAddress addr = p.getAddress();
554 if (addr.isMulticastAddress())
555 s.checkMulticast(addr);
557 s.checkConnect(addr.getHostAddress(), p.getPort());
562 if (p.getAddress () != null && (remoteAddress != p.getAddress () ||
563 remotePort != p.getPort ()))
564 throw new IllegalArgumentException (
565 "DatagramPacket address does not match remote address" );
568 // FIXME: if this is a subclass of MulticastSocket,
569 // use getTimeToLive for TTL val.
571 if (ch != null && !ch.isBlocking ())
572 throw new IllegalBlockingModeException ();
578 * Binds the socket to the given socket address.
580 * @param address The socket address to bind to.
582 * @exception SocketException If an error occurs.
583 * @exception SecurityException If a security manager exists and
584 * its checkListen method doesn't allow the operation.
585 * @exception IllegalArgumentException If address type is not supported.
589 public void bind (SocketAddress address)
590 throws SocketException
592 if (! (address instanceof InetSocketAddress))
593 throw new IllegalArgumentException ();
595 InetSocketAddress tmp = (InetSocketAddress) address;
597 SecurityManager s = System.getSecurityManager ();
599 s.checkListen(tmp.getPort ());
601 impl.bind (tmp.getPort (), tmp.getAddress ());
605 * Checks if the datagram socket is closed.
609 public boolean isClosed()
615 * Returns the datagram channel assoziated with this datagram socket.
619 public DatagramChannel getChannel()
625 * Connects the datagram socket to a specified socket address.
627 * @param address The socket address to connect to.
629 * @exception SocketException If an error occurs.
630 * @exception IllegalArgumentException If address type is not supported.
634 public void connect (SocketAddress address) throws SocketException
636 if ( !(address instanceof InetSocketAddress) )
637 throw new IllegalArgumentException (
638 "SocketAddress is not InetSocketAddress");
640 InetSocketAddress tmp = (InetSocketAddress) address;
641 connect( tmp.getAddress(), tmp.getPort());
645 * Returns the binding state of the socket.
649 public boolean isBound()
653 Object bindaddr = impl.getOption (SocketOptions.SO_BINDADDR);
655 catch (SocketException e)
664 * Returns the connection state of the socket.
668 public boolean isConnected()
670 return remoteAddress != null;
674 * Returns the SocketAddress of the host this socket is conneted to
675 * or null if this socket is not connected.
679 public SocketAddress getRemoteSocketAddress()
684 return new InetSocketAddress (remoteAddress, remotePort);
688 * Returns the local SocketAddress this socket is bound to
689 * or null if it is not bound.
693 public SocketAddress getLocalSocketAddress()
699 addr = (InetAddress) impl.getOption (SocketOptions.SO_BINDADDR);
701 catch (SocketException e)
706 return new InetSocketAddress (addr, impl.localPort);
710 * Enables/Disables SO_REUSEADDR.
712 * @param on Whether or not to have SO_REUSEADDR turned on.
714 * @exception SocketException If an error occurs.
718 public void setReuseAddress(boolean on) throws SocketException
721 throw new SocketException ("Cannot initialize Socket implementation");
723 impl.setOption (SocketOptions.SO_REUSEADDR, new Boolean (on));
727 * Checks if SO_REUSEADDR is enabled.
729 * @exception SocketException If an error occurs.
733 public boolean getReuseAddress() throws SocketException
736 throw new SocketException ("Cannot initialize Socket implementation");
738 Object obj = impl.getOption (SocketOptions.SO_REUSEADDR);
740 if (obj instanceof Boolean)
741 return(((Boolean) obj).booleanValue ());
743 throw new SocketException ("Unexpected type");
747 * Enables/Disables SO_BROADCAST
749 * @param on Whether or not to have SO_BROADCAST turned on
751 * @exception SocketException If an error occurs
755 public void setBroadcast(boolean on) throws SocketException
758 throw new SocketException ("Cannot initialize Socket implementation");
760 impl.setOption (SocketOptions.SO_BROADCAST, new Boolean (on));
764 * Checks if SO_BROADCAST is enabled
766 * @exception SocketException If an error occurs
770 public boolean getBroadcast() throws SocketException
773 throw new SocketException ("Cannot initialize Socket implementation");
775 Object obj = impl.getOption (SocketOptions.SO_BROADCAST);
777 if (obj instanceof Boolean)
778 return ((Boolean) obj).booleanValue ();
780 throw new SocketException ("Unexpected type");
784 * Sets the traffic class value
786 * @param tc The traffic class
788 * @exception SocketException If an error occurs
789 * @exception IllegalArgumentException If tc value is illegal
791 * @see DatagramSocket#getTrafficClass()
795 public void setTrafficClass(int tc)
796 throws SocketException
799 throw new SocketException ("Cannot initialize Socket implementation");
801 if (tc < 0 || tc > 255)
802 throw new IllegalArgumentException();
804 impl.setOption (SocketOptions.IP_TOS, new Integer (tc));
808 * Returns the current traffic class
810 * @see DatagramSocket#setTrafficClass(int tc)
812 * @exception SocketException If an error occurs
816 public int getTrafficClass() throws SocketException
819 throw new SocketException( "Cannot initialize Socket implementation");
821 Object obj = impl.getOption(SocketOptions.IP_TOS);
823 if (obj instanceof Integer)
824 return ((Integer) obj).intValue ();
826 throw new SocketException ("Unexpected type");
830 * Sets the datagram socket implementation factory for the application
832 * @param fac The factory to set
834 * @exception IOException If an error occurs
835 * @exception SocketException If the factory is already defined
836 * @exception SecurityException If a security manager exists and its
837 * checkSetFactory method doesn't allow the operation
839 public static void setDatagramSocketImplFactory
840 (DatagramSocketImplFactory fac) throws IOException
843 throw new SocketException ("DatagramSocketImplFactory already defined");
845 SecurityManager sm = System.getSecurityManager();
847 sm.checkSetFactory();