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