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