Source for java.net.Socket

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