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