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