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