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