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