InetAddress.java: Merged class documentation with classpath.
[gcc.git] / libjava / java / net / Socket.java
1 /* Socket.java -- Client socket implementation
2 Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
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)
9 any later version.
10
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.
15
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
19 02111-1307 USA.
20
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
24 combination.
25
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. */
37
38 package java.net;
39
40 import java.io.*;
41 import java.nio.channels.SocketChannel;
42 import java.nio.channels.IllegalBlockingModeException;
43
44 /* Written using on-line Java Platform 1.2 API Specification.
45 * Status: I believe all methods are implemented.
46 */
47
48 /**
49 * This class models a client site socket. A socket is a TCP/IP endpoint
50 * for network communications conceptually similar to a file handle.
51 * <p>
52 * This class does not actually do any work. Instead, it redirects all of
53 * its calls to a socket implementation object which implements the
54 * <code>SocketImpl</code> interface. The implementation class is
55 * instantiated by factory class that implements the
56 * <code>SocketImplFactory interface</code>. A default
57 * factory is provided, however the factory may be set by a call to
58 * the <code>setSocketImplFactory</code> method. Note that this may only be
59 * done once per virtual machine. If a subsequent attempt is made to set the
60 * factory, a <code>SocketException</code> will be thrown.
61 *
62 * @author Aaron M. Renn (arenn@urbanophile.com)
63 * @author Per Bothner (bothner@cygnus.com)
64 */
65 public class Socket
66 {
67
68 // Class Variables
69
70 /**
71 * This is the user SocketImplFactory for this class. If this variable is
72 * null, a default factory is used.
73 */
74 static SocketImplFactory factory;
75
76 // Instance Variables
77
78 /**
79 * The implementation object to which calls are redirected
80 */
81 SocketImpl impl;
82
83 private boolean inputShutdown;
84 private boolean outputShutdown;
85
86 SocketChannel ch; // this field must have been set if created by SocketChannel
87
88 private boolean closed = false;
89
90 // Constructors
91
92 /**
93 * Initializes a new instance of <code>Socket</code> object without
94 * connecting to a remote host. This useful for subclasses of socket that
95 * might want this behavior.
96 *
97 * @specnote This constructor is public since JDK 1.4
98 * @since 1.1
99 */
100 public Socket ()
101 {
102 if (factory != null)
103 impl = factory.createSocketImpl();
104 else
105 impl = new PlainSocketImpl();
106
107 inputShutdown = false;
108 outputShutdown = false;
109 }
110
111 /**
112 * Initializes a new instance of <code>Socket</code> object without
113 * connecting to a remote host. This is useful for subclasses of socket
114 * that might want this behavior.
115 * <p>
116 * Additionally, this socket will be created using the supplied
117 * implementation class instead the default class or one returned by a
118 * factory. This value can be <code>null</code>, but if it is, all instance
119 * methods in <code>Socket</code> should be overridden because most of them
120 * rely on this value being populated.
121 *
122 * @param impl The <code>SocketImpl</code> to use for this
123 * <code>Socket</code>
124 *
125 * @exception SocketException If an error occurs
126 *
127 * @since 1.1
128 */
129 protected Socket (SocketImpl impl) throws SocketException
130 {
131 this.impl = impl;
132 this.inputShutdown = false;
133 this.outputShutdown = false;
134 }
135
136 /**
137 * Initializes a new instance of <code>Socket</code> and connects to the
138 * hostname and port specified as arguments.
139 *
140 * @param host The name of the host to connect to
141 * @param port The port number to connect to
142 *
143 * @exception UnknownHostException If the hostname cannot be resolved to a
144 * network address.
145 * @exception IOException If an error occurs
146 * @exception SecurityException If a security manager exists and its
147 * checkConnect method doesn't allow the operation
148 */
149 public Socket (String host, int port)
150 throws UnknownHostException, IOException
151 {
152 this(InetAddress.getByName(host), port, null, 0, true);
153 }
154
155 /**
156 * Initializes a new instance of <code>Socket</code> and connects to the
157 * address and port number specified as arguments.
158 *
159 * @param address The address to connect to
160 * @param port The port number to connect to
161 *
162 * @exception IOException If an error occurs
163 * @exception SecurityException If a security manager exists and its
164 * checkConnect method doesn't allow the operation
165 */
166 public Socket (InetAddress address, int port)
167 throws IOException
168 {
169 this(address, port, null, 0, true);
170 }
171
172 /**
173 * Initializes a new instance of <code>Socket</code> that connects to the
174 * named host on the specified port and binds to the specified local address
175 * and port.
176 *
177 * @param host The name of the remote host to connect to.
178 * @param port The remote port to connect to.
179 * @param loadAddr The local address to bind to.
180 * @param localPort The local port to bind to.
181 *
182 * @exception SecurityException If the <code>SecurityManager</code>
183 * exists and does not allow a connection to the specified host/port or
184 * binding to the specified local host/port.
185 * @exception IOException If a connection error occurs.
186 *
187 * @since 1.1
188 */
189 public Socket (String host, int port,
190 InetAddress localAddr, int localPort) throws IOException
191 {
192 this(InetAddress.getByName(host), port, localAddr, localPort, true);
193 }
194
195 /**
196 * Initializes a new instance of <code>Socket</code> and connects to the
197 * address and port number specified as arguments, plus binds to the
198 * specified local address and port.
199 *
200 * @param address The remote address to connect to
201 * @param port The remote port to connect to
202 * @param localAddr The local address to connect to
203 * @param localPort The local port to connect to
204 *
205 * @exception IOException If an error occurs
206 * @exception SecurityException If a security manager exists and its
207 * checkConnect method doesn't allow the operation
208 *
209 * @since 1.1
210 */
211 public Socket (InetAddress address, int port,
212 InetAddress localAddr, int localPort) throws IOException
213 {
214 this(address, port, localAddr, localPort, true);
215 }
216
217 /**
218 * Initializes a new instance of <code>Socket</code> and connects to the
219 * hostname and port specified as arguments. If the stream argument is set
220 * to <code>true</code>, then a stream socket is created. If it is
221 * <code>false</code>, a datagram socket is created.
222 *
223 * @param host The name of the host to connect to
224 * @param port The port to connect to
225 * @param stream <code>true</code> for a stream socket, <code>false</code>
226 * for a datagram socket
227 *
228 * @exception IOException If an error occurs
229 * @exception SecurityException If a security manager exists and its
230 * checkConnect method doesn't allow the operation
231 *
232 * @deprecated Use the <code>DatagramSocket</code> class to create
233 * datagram oriented sockets.
234 */
235 public Socket (String host, int port, boolean stream) throws IOException
236 {
237 this(InetAddress.getByName(host), port, null, 0, stream);
238 }
239
240 /**
241 * Initializes a new instance of <code>Socket</code> and connects to the
242 * address and port number specified as arguments. If the stream param is
243 * <code>true</code>, a stream socket will be created, otherwise a datagram
244 * socket is created.
245 *
246 * @param host The address to connect to
247 * @param port The port number to connect to
248 * @param stream <code>true</code> to create a stream socket,
249 * <code>false</code> to create a datagram socket.
250 *
251 * @exception IOException If an error occurs
252 * @exception SecurityException If a security manager exists and its
253 * checkConnect method doesn't allow the operation
254 *
255 * @deprecated Use the <code>DatagramSocket</code> class to create
256 * datagram oriented sockets.
257 */
258 public Socket (InetAddress host, int port, boolean stream) throws IOException
259 {
260 this(host, port, null, 0, stream);
261 }
262
263 /**
264 * This constructor is where the real work takes place. Connect to the
265 * specified address and port. Use default local values if not specified,
266 * otherwise use the local host and port passed in. Create as stream or
267 * datagram based on "stream" argument.
268 * <p>
269 *
270 * @param raddr The remote address to connect to
271 * @param rport The remote port to connect to
272 * @param laddr The local address to connect to
273 * @param lport The local port to connect to
274 * @param stream true for a stream socket, false for a datagram socket
275 *
276 * @exception IOException If an error occurs
277 * @exception SecurityException If a security manager exists and its
278 * checkConnect method doesn't allow the operation
279 */
280 private Socket(InetAddress raddr, int rport, InetAddress laddr, int lport,
281 boolean stream) throws IOException
282 {
283 this();
284 this.inputShutdown = false;
285 this.outputShutdown = false;
286
287 if (impl == null)
288 throw new IOException("Cannot initialize Socket implementation");
289
290 SecurityManager sm = System.getSecurityManager();
291 if (sm != null)
292 sm.checkConnect(raddr.getHostName(), rport);
293
294 // create socket
295 impl.create(stream);
296
297 // FIXME: JCL p. 1586 says if localPort is unspecified, bind to any port,
298 // i.e. '0' and if localAddr is unspecified, use getLocalAddress() as
299 // that default. JDK 1.2 doc infers not to do a bind.
300
301 // bind/connect to address/port
302 if (laddr != null)
303 {
304 try
305 {
306 impl.bind(laddr, lport);
307 }
308 catch (IOException exception)
309 {
310 impl.close();
311 throw exception;
312 }
313 catch (RuntimeException exception)
314 {
315 impl.close();
316 throw exception;
317 }
318 catch (Error error)
319 {
320 impl.close();
321 throw error;
322 }
323 }
324
325 if (raddr != null)
326 {
327 try
328 {
329 impl.connect(raddr, rport);
330 }
331 catch (IOException exception)
332 {
333 impl.close();
334 throw exception;
335 }
336 catch (RuntimeException exception)
337 {
338 impl.close();
339 throw exception;
340 }
341 catch (Error error)
342 {
343 impl.close();
344 throw error;
345 }
346 }
347 }
348
349 /**
350 * Binds the socket to the givent local address/port
351 *
352 * @param bindpoint The address/port to bind to
353 *
354 * @exception IOException If an error occurs
355 * @exception SecurityException If a security manager exists and its
356 * checkConnect method doesn't allow the operation
357 * @exception IllegalArgumentException If the address type is not supported
358 *
359 * @since 1.4
360 */
361 public void bind (SocketAddress bindpoint) throws IOException
362 {
363 if (closed)
364 throw new SocketException ("Socket is closed");
365
366 if ( !(bindpoint instanceof InetSocketAddress))
367 throw new IllegalArgumentException ();
368
369 InetSocketAddress tmp = (InetSocketAddress) bindpoint;
370 impl.bind (tmp.getAddress(), tmp.getPort());
371 }
372
373 /**
374 * Connects the socket with a remote address.
375 *
376 * @param endpoint The address to connect to
377 *
378 * @exception IOException If an error occurs
379 * @exception IllegalArgumentException If the addess type is not supported
380 * @exception IllegalBlockingModeException If this socket has an associated
381 * channel, and the channel is in non-blocking mode
382 *
383 * @since 1.4
384 */
385 public void connect (SocketAddress endpoint)
386 throws IOException
387 {
388 if (closed)
389 throw new SocketException ("Socket is closed");
390
391 if (! (endpoint instanceof InetSocketAddress))
392 throw new IllegalArgumentException ("Address type not supported");
393
394 if (ch != null && !ch.isBlocking ())
395 throw new IllegalBlockingModeException ();
396
397 impl.connect (endpoint, 0);
398 }
399
400 /**
401 * Connects the socket with a remote address. A timeout of zero is
402 * interpreted as an infinite timeout. The connection will then block
403 * until established or an error occurs.
404 *
405 * @param endpoint The address to connect to
406 *
407 * @exception IOException If an error occurs
408 * @exception IllegalArgumentException If the address type is not supported
409 * @exception IllegalBlockingModeException If this socket has an associated
410 * channel, and the channel is in non-blocking mode
411 * @exception SocketTimeoutException If the timeout is reached
412 *
413 * @since 1.4
414 */
415 public void connect (SocketAddress endpoint, int timeout)
416 throws IOException
417 {
418 if (closed)
419 throw new SocketException ("Socket is closed");
420
421 if (! (endpoint instanceof InetSocketAddress))
422 throw new IllegalArgumentException ("Address type not supported");
423
424 if (ch != null && !ch.isBlocking ())
425 throw new IllegalBlockingModeException ();
426
427 impl.connect (endpoint, timeout);
428 }
429
430 /**
431 * Returns the address of the remote end of the socket. If this socket
432 * is not connected, then <code>null</code> is returned.
433 *
434 * @return The remote address this socket is connected to
435 */
436 public InetAddress getInetAddress ()
437 {
438 if (impl != null)
439 return impl.getInetAddress();
440
441 return null;
442 }
443
444 /**
445 * Returns the local address to which this socket is bound. If this socket
446 * is not connected, then <code>null</code> is returned.
447 *
448 * @return The local address
449 *
450 * @since 1.1
451 */
452 public InetAddress getLocalAddress ()
453 {
454 if (impl == null)
455 return null;
456
457 InetAddress addr = null;
458 try
459 {
460 addr = (InetAddress)impl.getOption(SocketOptions.SO_BINDADDR);
461 }
462 catch(SocketException e)
463 {
464 // (hopefully) shouldn't happen
465 // throw new java.lang.InternalError
466 // ("Error in PlainSocketImpl.getOption");
467 return null;
468 }
469
470 // FIXME: According to libgcj, checkConnect() is supposed to be called
471 // before performing this operation. Problems: 1) We don't have the
472 // addr until after we do it, so we do a post check. 2). The docs I
473 // see don't require this in the Socket case, only DatagramSocket, but
474 // we'll assume they mean both.
475 SecurityManager sm = System.getSecurityManager();
476 if (sm != null)
477 sm.checkConnect(addr.getHostName(), getLocalPort());
478
479 return addr;
480 }
481
482 /**
483 * Returns the port number of the remote end of the socket connection. If
484 * this socket is not connected, then -1 is returned.
485 *
486 * @return The remote port this socket is connected to
487 */
488 public int getPort ()
489 {
490 if (impl != null)
491 return impl.getPort();
492
493 return -1;
494 }
495
496 /**
497 * Returns the local port number to which this socket is bound. If this
498 * socket is not connected, then -1 is returned.
499 *
500 * @return The local port
501 */
502 public int getLocalPort ()
503 {
504 if (impl != null)
505 return impl.getLocalPort();
506
507 return -1;
508 }
509
510 /**
511 * If the socket is already bound this returns the local SocketAddress,
512 * otherwise null
513 *
514 * @since 1.4
515 */
516 public SocketAddress getLocalSocketAddress()
517 {
518 InetAddress addr = getLocalAddress ();
519
520 if (addr == null)
521 return null;
522
523 return new InetSocketAddress (addr, impl.getLocalPort());
524 }
525
526 /**
527 * If the socket is already connected this returns the remote SocketAddress,
528 * otherwise null
529 *
530 * @since 1.4
531 */
532 public SocketAddress getRemoteSocketAddress()
533 {
534 if (!isConnected ())
535 return null;
536
537 return new InetSocketAddress (impl.getInetAddress (), impl.getPort ());
538 }
539
540 /**
541 * Returns an InputStream for reading from this socket.
542 *
543 * @return The InputStream object
544 *
545 * @exception IOException If an error occurs or Socket is not connected
546 */
547 public InputStream getInputStream () throws IOException
548 {
549 if (impl != null)
550 return(impl.getInputStream());
551
552 throw new IOException("Not connected");
553 }
554
555 /**
556 * Returns an OutputStream for writing to this socket.
557 *
558 * @return The OutputStream object
559 *
560 * @exception IOException If an error occurs or Socket is not connected
561 */
562 public OutputStream getOutputStream () throws IOException
563 {
564 if (impl != null)
565 return impl.getOutputStream();
566
567 throw new IOException("Not connected");
568 }
569
570 /**
571 * Sets the TCP_NODELAY option on the socket.
572 *
573 * @param on true to enable, false to disable
574 *
575 * @exception SocketException If an error occurs or Socket is not connected
576 *
577 * @since 1.1
578 */
579 public void setTcpNoDelay (boolean on) throws SocketException
580 {
581 if (impl == null)
582 throw new SocketException("Not connected");
583
584 impl.setOption(SocketOptions.TCP_NODELAY, new Boolean(on));
585 }
586
587 /**
588 * Tests whether or not the TCP_NODELAY option is set on the socket.
589 * Returns true if enabled, false if disabled. When on it disables the
590 * Nagle algorithm which means that packets are always send immediatly and
591 * never merged together to reduce network trafic.
592 *
593 * @return Whether or not TCP_NODELAY is set
594 *
595 * @exception SocketException If an error occurs or Socket not connected
596 *
597 * @since 1.1
598 */
599 public boolean getTcpNoDelay() throws SocketException
600 {
601 if (impl == null)
602 throw new SocketException("Not connected");
603
604 Object on = impl.getOption(SocketOptions.TCP_NODELAY);
605
606 if (on instanceof Boolean)
607 return(((Boolean)on).booleanValue());
608 else
609 throw new SocketException("Internal Error");
610 }
611
612 /**
613 * Sets the value of the SO_LINGER option on the socket. If the
614 * SO_LINGER option is set on a socket and there is still data waiting to
615 * be sent when the socket is closed, then the close operation will block
616 * until either that data is delivered or until the timeout period
617 * expires. The linger interval is specified in hundreths of a second
618 * (platform specific?)
619 *
620 * @param on true to enable SO_LINGER, false to disable
621 * @param linger The SO_LINGER timeout in hundreths of a second or -1 if
622 * SO_LINGER not set.
623 *
624 * @exception SocketException If an error occurs or Socket not connected
625 * @exception IllegalArgumentException If linger is negative
626 *
627 * @since 1.1
628 */
629 public void setSoLinger(boolean on, int linger) throws SocketException
630 {
631 if (impl == null)
632 throw new SocketException("No socket created");
633
634 if (on == true)
635 {
636 if (linger < 0)
637 throw new IllegalArgumentException("SO_LINGER must be >= 0");
638
639 if (linger > 65535)
640 linger = 65535;
641
642 impl.setOption(SocketOptions.SO_LINGER, new Integer(linger));
643 }
644 else
645 {
646 impl.setOption(SocketOptions.SO_LINGER, new Boolean(false));
647 }
648 }
649
650 /**
651 * Returns the value of the SO_LINGER option on the socket. If the
652 * SO_LINGER option is set on a socket and there is still data waiting to
653 * be sent when the socket is closed, then the close operation will block
654 * until either that data is delivered or until the timeout period
655 * expires. This method either returns the timeouts (in hundredths of
656 * of a second (platform specific?)) if SO_LINGER is set, or -1 if
657 * SO_LINGER is not set.
658 *
659 * @return The SO_LINGER timeout in hundreths of a second or -1
660 * if SO_LINGER not set
661 *
662 * @exception SocketException If an error occurs or Socket is not connected
663 *
664 * @since 1.1
665 */
666 public int getSoLinger() throws SocketException
667 {
668 if (impl == null)
669 throw new SocketException("Not connected");
670
671 Object linger = impl.getOption(SocketOptions.SO_LINGER);
672 if (linger instanceof Integer)
673 return(((Integer)linger).intValue());
674 else
675 return -1;
676 }
677
678 /**
679 * Sends urgent data through the socket
680 *
681 * @param data The data to send.
682 * Only the lowest eight bits of data are sent
683 *
684 * @exception IOException If an error occurs
685 *
686 * @since 1.4
687 */
688 public void sendUrgentData (int data) throws IOException
689 {
690 impl.sendUrgentData (data);
691 }
692
693 /**
694 * Enables/disables the SO_OOBINLINE option
695 *
696 * @param on True if SO_OOBLINE should be enabled
697 *
698 * @exception SocketException If an error occurs
699 *
700 * @since 1.4
701 */
702 public void setOOBInline (boolean on) throws SocketException
703 {
704 if (impl == null)
705 throw new SocketException("Not connected");
706
707 impl.setOption(SocketOptions.SO_OOBINLINE, new Boolean(on));
708 }
709
710 /**
711 * Returns the current setting of the SO_OOBINLINE option for this socket
712 *
713 * @exception SocketException If an error occurs
714 *
715 * @since 1.4
716 */
717 public boolean getOOBInline () throws SocketException
718 {
719 if (impl == null)
720 throw new SocketException("Not connected");
721
722 Object buf = impl.getOption(SocketOptions.SO_OOBINLINE);
723
724 if (buf instanceof Boolean)
725 return(((Boolean)buf).booleanValue());
726 else
727 throw new SocketException("Internal Error: Unexpected type");
728 }
729
730 /**
731 * Sets the value of the SO_TIMEOUT option on the socket. If this value
732 * is set, and an read/write is performed that does not complete within
733 * the timeout period, a short count is returned (or an EWOULDBLOCK signal
734 * would be sent in Unix if no data had been read). A value of 0 for
735 * this option implies that there is no timeout (ie, operations will
736 * block forever). On systems that have separate read and write timeout
737 * values, this method returns the read timeout. This
738 * value is in milliseconds.
739 *
740 * @param timeout The length of the timeout in milliseconds, or
741 * 0 to indicate no timeout.
742 *
743 * @exception SocketException If an error occurs or Socket not connected
744 *
745 * @since 1.1
746 */
747 public synchronized void setSoTimeout (int timeout) throws SocketException
748 {
749 if (impl == null)
750 throw new SocketException("Not connected");
751
752 if (timeout < 0)
753 throw new IllegalArgumentException("SO_TIMEOUT value must be >= 0");
754
755 impl.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
756 }
757
758 /**
759 * Returns the value of the SO_TIMEOUT option on the socket. If this value
760 * is set, and an read/write is performed that does not complete within
761 * the timeout period, a short count is returned (or an EWOULDBLOCK signal
762 * would be sent in Unix if no data had been read). A value of 0 for
763 * this option implies that there is no timeout (ie, operations will
764 * block forever). On systems that have separate read and write timeout
765 * values, this method returns the read timeout. This
766 * value is in thousandths of a second (implementation specific?).
767 *
768 * @return The length of the timeout in thousandth's of a second or 0
769 * if not set
770 *
771 * @exception SocketException If an error occurs or Socket not connected
772 *
773 * @since 1.1
774 */
775 public synchronized int getSoTimeout () throws SocketException
776 {
777 if (impl == null)
778 throw new SocketException("Not connected");
779
780 Object timeout = impl.getOption(SocketOptions.SO_TIMEOUT);
781 if (timeout instanceof Integer)
782 return(((Integer)timeout).intValue());
783 else
784 return 0;
785 }
786
787 /**
788 * This method sets the value for the system level socket option
789 * SO_SNDBUF to the specified value. Note that valid values for this
790 * option are specific to a given operating system.
791 *
792 * @param size The new send buffer size.
793 *
794 * @exception SocketException If an error occurs or Socket not connected
795 * @exception IllegalArgumentException If size is 0 or negative
796 *
797 * @since 1.2
798 */
799 public void setSendBufferSize (int size) throws SocketException
800 {
801 if (impl == null)
802 throw new SocketException("Not connected");
803
804 if (size <= 0)
805 throw new IllegalArgumentException("SO_SNDBUF value must be > 0");
806
807 impl.setOption(SocketOptions.SO_SNDBUF, new Integer(size));
808 }
809
810 /**
811 * This method returns the value of the system level socket option
812 * SO_SNDBUF, which is used by the operating system to tune buffer
813 * sizes for data transfers.
814 *
815 * @return The send buffer size.
816 *
817 * @exception SocketException If an error occurs or socket not connected
818 *
819 * @since 1.2
820 */
821 public int getSendBufferSize () throws SocketException
822 {
823 if (impl == null)
824 throw new SocketException("Not connected");
825
826 Object buf = impl.getOption(SocketOptions.SO_SNDBUF);
827
828 if (buf instanceof Integer)
829 return(((Integer)buf).intValue());
830 else
831 throw new SocketException("Internal Error: Unexpected type");
832 }
833
834 /**
835 * This method sets the value for the system level socket option
836 * SO_RCVBUF to the specified value. Note that valid values for this
837 * option are specific to a given operating system.
838 *
839 * @param size The new receive buffer size.
840 *
841 * @exception SocketException If an error occurs or Socket is not connected
842 * @exception IllegalArgumentException If size is 0 or negative
843 *
844 * @since 1.2
845 */
846 public void setReceiveBufferSize (int size) throws SocketException
847 {
848 if (impl == null)
849 throw new SocketException("Not connected");
850
851 if (size <= 0)
852 throw new IllegalArgumentException("SO_RCVBUF value must be > 0");
853
854 impl.setOption(SocketOptions.SO_RCVBUF, new Integer(size));
855 }
856
857 /**
858 * This method returns the value of the system level socket option
859 * SO_RCVBUF, which is used by the operating system to tune buffer
860 * sizes for data transfers.
861 *
862 * @return The receive buffer size.
863 *
864 * @exception SocketException If an error occurs or Socket is not connected
865 *
866 * @since 1.2
867 */
868 public int getReceiveBufferSize () throws SocketException
869 {
870 if (impl == null)
871 throw new SocketException("Not connected");
872
873 Object buf = impl.getOption(SocketOptions.SO_RCVBUF);
874
875 if (buf instanceof Integer)
876 return(((Integer)buf).intValue());
877 else
878 throw new SocketException("Internal Error: Unexpected type");
879 }
880
881 /**
882 * This method sets the value for the socket level socket option
883 * SO_KEEPALIVE.
884 *
885 * @param on True if SO_KEEPALIVE should be enabled
886 *
887 * @exception SocketException If an error occurs or Socket is not connected
888 *
889 * @since 1.3
890 */
891 public void setKeepAlive (boolean on) throws SocketException
892 {
893 if (impl == null)
894 throw new SocketException("Not connected");
895
896 impl.setOption(SocketOptions.SO_KEEPALIVE, new Boolean(on));
897 }
898
899 /**
900 * This method returns the value of the socket level socket option
901 * SO_KEEPALIVE.
902 *
903 * @return The setting
904 *
905 * @exception SocketException If an error occurs or Socket is not connected
906 *
907 * @since 1.3
908 */
909 public boolean getKeepAlive () throws SocketException
910 {
911 if (impl == null)
912 throw new SocketException("Not connected");
913
914 Object buf = impl.getOption(SocketOptions.SO_KEEPALIVE);
915
916 if (buf instanceof Boolean)
917 return(((Boolean)buf).booleanValue());
918 else
919 throw new SocketException("Internal Error: Unexpected type");
920 }
921
922 /**
923 * Closes the socket.
924 *
925 * @exception IOException If an error occurs
926 */
927 public synchronized void close () throws IOException
928 {
929 if (impl != null)
930 impl.close();
931
932 if (ch != null)
933 ch.close();
934
935 closed = true;
936 }
937
938 /**
939 * Converts this <code>Socket</code> to a <code>String</code>.
940 *
941 * @return The <code>String</code> representation of this <code>Socket</code>
942 */
943 public String toString ()
944 {
945 return("Socket " + impl);
946 }
947
948 // Class Methods
949
950 /**
951 * Sets the <code>SocketImplFactory</code>. This may be done only once per
952 * virtual machine. Subsequent attempts will generate a
953 * <code>SocketException</code>. Note that a <code>SecurityManager</code>
954 * check is made prior to setting the factory. If
955 * insufficient privileges exist to set the factory, then an
956 * <code>IOException</code> will be thrown.
957 *
958 * @exception SecurityException If the <code>SecurityManager</code> does
959 * not allow this operation.
960 * @exception SocketException If the SocketImplFactory is already defined
961 * @exception IOException If any other error occurs
962 */
963 public static synchronized void setSocketImplFactory (SocketImplFactory fac)
964 throws IOException
965 {
966 // See if already set
967 if (factory != null)
968 throw new SocketException("SocketImplFactory already defined");
969
970 // Check permissions
971 SecurityManager sm = System.getSecurityManager();
972 if (sm != null)
973 sm.checkSetFactory();
974
975 if (fac == null)
976 throw new SocketException("SocketImplFactory cannot be null");
977
978 factory = fac;
979 }
980
981 /**
982 * Closes the input side of the socket stream.
983 *
984 * @exception IOException If an error occurs.
985 *
986 * @since 1.3
987 */
988 public void shutdownInput() throws IOException
989 {
990 if (impl != null)
991 impl.shutdownInput();
992
993 inputShutdown = true;
994 }
995
996 /**
997 * Closes the output side of the socket stream.
998 *
999 * @exception IOException If an error occurs.
1000 *
1001 * @since 1.3
1002 */
1003 public void shutdownOutput() throws IOException
1004 {
1005 if (impl != null)
1006 impl.shutdownOutput();
1007
1008 outputShutdown = true;
1009 }
1010
1011 /**
1012 * Returns the socket channel associated with this socket.
1013 *
1014 * It returns null if no associated socket exists.
1015 *
1016 * @since 1.4
1017 */
1018 public SocketChannel getChannel()
1019 {
1020 return ch;
1021 }
1022
1023 /**
1024 * Checks if the SO_REUSEADDR option is enabled
1025 *
1026 * @exception SocketException If an error occurs
1027 *
1028 * @since 1.4
1029 */
1030 public boolean getReuseAddress () throws SocketException
1031 {
1032 if (impl == null)
1033 throw new SocketException ("Cannot initialize Socket implementation");
1034
1035 Object reuseaddr = impl.getOption (SocketOptions.SO_REUSEADDR);
1036
1037 if (!(reuseaddr instanceof Boolean))
1038 throw new SocketException ("Internal Error");
1039
1040 return ((Boolean) reuseaddr).booleanValue ();
1041 }
1042
1043 /**
1044 * Enables/Disables the SO_REUSEADDR option
1045 *
1046 * @exception SocketException If an error occurs
1047 *
1048 * @since 1.4
1049 */
1050 public void setReuseAddress (boolean on) throws SocketException
1051 {
1052 if (impl == null)
1053 throw new SocketException ("Cannot initialize Socket implementation");
1054
1055 impl.setOption (SocketOptions.SO_REUSEADDR, new Boolean (on));
1056 }
1057
1058 /**
1059 * Returns the current traffic class
1060 *
1061 * @exception SocketException If an error occurs
1062 *
1063 * @see Socket#setTrafficClass(int tc)
1064 *
1065 * @since 1.4
1066 */
1067 public int getTrafficClass () throws SocketException
1068 {
1069 if (impl == null)
1070 throw new SocketException ("Cannot initialize Socket implementation");
1071
1072 Object obj = impl.getOption(SocketOptions.IP_TOS);
1073
1074 if (obj instanceof Integer)
1075 return ((Integer) obj).intValue ();
1076 else
1077 throw new SocketException ("Unexpected type");
1078 }
1079
1080 /**
1081 * Sets the traffic class value
1082 *
1083 * @param tc The traffic class
1084 *
1085 * @exception SocketException If an error occurs
1086 * @exception IllegalArgumentException If tc value is illegal
1087 *
1088 * @see Socket#getTrafficClass()
1089 *
1090 * @since 1.4
1091 */
1092 public void setTrafficClass (int tc) throws SocketException
1093 {
1094 if (impl == null)
1095 throw new SocketException ("Cannot initialize Socket implementation");
1096
1097 if (tc < 0 || tc > 255)
1098 throw new IllegalArgumentException();
1099
1100 impl.setOption (SocketOptions.IP_TOS, new Integer (tc));
1101 }
1102
1103 /**
1104 * Checks if the socket is connected
1105 *
1106 * @since 1.4
1107 */
1108 public boolean isConnected ()
1109 {
1110 return impl.getInetAddress () != null;
1111 }
1112
1113 /**
1114 * Checks if the socket is already bound.
1115 *
1116 * @since 1.4
1117 */
1118 public boolean isBound ()
1119 {
1120 return getLocalAddress () != null;
1121 }
1122
1123 /**
1124 * Checks if the socket is closed.
1125 *
1126 * @since 1.4
1127 */
1128 public boolean isClosed ()
1129 {
1130 return closed;
1131 }
1132
1133 /**
1134 * Checks if the socket's input stream is shutdown
1135 *
1136 * @since 1.4
1137 */
1138 public boolean isInputShutdown ()
1139 {
1140 return inputShutdown;
1141 }
1142
1143 /**
1144 * Checks if the socket's output stream is shutdown
1145 *
1146 * @since 1.4
1147 */
1148 public boolean isOutputShutdown ()
1149 {
1150 return outputShutdown;
1151 }
1152 }