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