Source for java.net.Socket

   1: /* Socket.java -- Client socket implementation
   2:    Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2006, 2007
   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 impl.create() has been called.
  87:    */
  88:   // package-private because ServerSocket.implAccept() needs to access it.
  89:   boolean implCreated;
  90: 
  91:   /**
  92:    * True if the socket is bound.
  93:    * Package private so it can be set from ServerSocket when accept is called.
  94:    */
  95:   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.getHostAddress(), rport);
 301: 
 302:     // bind socket
 303:     SocketAddress bindaddr =
 304:       laddr == null ? null : new InetSocketAddress(laddr, lport);
 305:     bind(bindaddr);
 306: 
 307:     // Connect socket in case of Exceptions we must close the socket
 308:     // because an exception in the constructor means that the caller will
 309:     // not have a reference to this instance.
 310:     // Note: You may have the idea that the exception treatment
 311:     // should be moved into connect() but there is a Mauve test which
 312:     // shows that a failed connect should not close the socket.
 313:     try
 314:       {
 315:         connect(new InetSocketAddress(raddr, rport));
 316:       }
 317:     catch (IOException ioe)
 318:       {
 319:         impl.close();
 320:         throw ioe;
 321:       }
 322:     catch (RuntimeException re)
 323:       {
 324:         impl.close();
 325:         throw re;
 326:       }
 327: 
 328:     // FIXME: JCL p. 1586 says if localPort is unspecified, bind to any port,
 329:     // i.e. '0' and if localAddr is unspecified, use getLocalAddress() as
 330:     // that default.  JDK 1.2 doc infers not to do a bind.
 331:   }
 332: 
 333:   private SocketImpl getImpl() throws SocketException
 334:   {
 335:     if (! implCreated)
 336:       {
 337:         try
 338:           {
 339:             impl.create(true);
 340:           }
 341:         catch (IOException x)
 342:           {
 343:             throw (SocketException) new SocketException().initCause(x);
 344:           }
 345:         implCreated = true;
 346:       }
 347:     return impl;
 348:   }
 349: 
 350:   /**
 351:    * Binds the socket to the given local address/port
 352:    *
 353:    * @param bindpoint The address/port to bind to
 354:    *
 355:    * @exception IOException If an error occurs
 356:    * @exception SecurityException If a security manager exists and its
 357:    * checkConnect method doesn't allow the operation
 358:    * @exception IllegalArgumentException If the address type is not supported
 359:    *
 360:    * @since 1.4
 361:    */
 362:   public void bind(SocketAddress bindpoint) throws IOException
 363:   {
 364:     if (isClosed())
 365:       throw new SocketException("socket is closed");
 366: 
 367:     // XXX: JDK 1.4.1 API documentation says that if bindpoint is null the
 368:     // socket will be bound to an ephemeral port and a valid local address.
 369:     if (bindpoint == null)
 370:       bindpoint = new InetSocketAddress(InetAddress.ANY_IF, 0);
 371: 
 372:     if (! (bindpoint instanceof InetSocketAddress))
 373:       throw new IllegalArgumentException();
 374: 
 375:     InetSocketAddress tmp = (InetSocketAddress) bindpoint;
 376: 
 377:     // bind to address/port
 378:     try
 379:       {
 380:         getImpl().bind(tmp.getAddress(), tmp.getPort());
 381:         bound = true;
 382:       }
 383:     catch (IOException exception)
 384:       {
 385:         close();
 386:         throw exception;
 387:       }
 388:     catch (RuntimeException exception)
 389:       {
 390:         close();
 391:         throw exception;
 392:       }
 393:     catch (Error error)
 394:       {
 395:         close();
 396:         throw error;
 397:       }
 398:   }
 399: 
 400:   /**
 401:    * Connects the socket with a remote address.
 402:    *
 403:    * @param endpoint The address to connect to
 404:    *
 405:    * @exception IOException If an error occurs
 406:    * @exception IllegalArgumentException If the addess type is not supported
 407:    * @exception IllegalBlockingModeException If this socket has an associated
 408:    * channel, and the channel is in non-blocking mode
 409:    *
 410:    * @since 1.4
 411:    */
 412:   public void connect(SocketAddress endpoint) throws IOException
 413:   {
 414:     connect(endpoint, 0);
 415:   }
 416: 
 417:   /**
 418:    * Connects the socket with a remote address. A timeout of zero is
 419:    * interpreted as an infinite timeout. The connection will then block
 420:    * until established or an error occurs.
 421:    *
 422:    * @param endpoint The address to connect to
 423:    * @param timeout The length of the timeout in milliseconds, or
 424:    * 0 to indicate no timeout.
 425:    *
 426:    * @exception IOException If an error occurs
 427:    * @exception IllegalArgumentException If the address type is not supported
 428:    * @exception IllegalBlockingModeException If this socket has an associated
 429:    * channel, and the channel is in non-blocking mode
 430:    * @exception SocketTimeoutException If the timeout is reached
 431:    * @throws SecurityException if the SocketAddress is an {@link InetSocketAddress}
 432:    *                           and a security manager is present which does not
 433:    *                           allow connections on the given host and port.
 434:    * @since 1.4
 435:    */
 436:   public void connect(SocketAddress endpoint, int timeout)
 437:     throws IOException
 438:   {
 439:     if (isClosed())
 440:       throw new SocketException("socket is closed");
 441: 
 442:     if (! (endpoint instanceof InetSocketAddress))
 443:       throw new IllegalArgumentException("unsupported address type");
 444: 
 445:     SecurityManager sm = System.getSecurityManager();
 446:     if (sm != null)
 447:       {
 448:         InetSocketAddress inetAddr = (InetSocketAddress) endpoint;
 449:         sm.checkConnect(inetAddr.getHostName(), inetAddr.getPort());
 450:       }
 451: 
 452:     // The Sun spec says that if we have an associated channel and
 453:     // it is in non-blocking mode, we throw an IllegalBlockingModeException.
 454:     // However, in our implementation if the channel itself initiated this
 455:     // operation, then we must honor it regardless of its blocking mode.
 456:     if (getChannel() != null && ! getChannel().isBlocking()
 457:         && ! ((PlainSocketImpl) getImpl()).isInChannelOperation())
 458:       throw new IllegalBlockingModeException();
 459: 
 460:     if (! isBound())
 461:       bind(null);
 462: 
 463:     getImpl().connect(endpoint, timeout);
 464:   }
 465: 
 466:   /**
 467:    * Returns the address of the remote end of the socket.  If this socket
 468:    * is not connected, then <code>null</code> is returned.
 469:    *
 470:    * @return The remote address this socket is connected to
 471:    */
 472:   public InetAddress getInetAddress()
 473:   {
 474:     if (! isConnected())
 475:       return null;
 476: 
 477:     try
 478:       {
 479:         return getImpl().getInetAddress();
 480:       }
 481:     catch (SocketException e)
 482:       {
 483:         // This cannot happen as we are connected.
 484:       }
 485: 
 486:     return null;
 487:   }
 488: 
 489:   /**
 490:    * Returns the local address to which this socket is bound.  If this socket
 491:    * is not connected, then a wildcard address, for which
 492:    * @see InetAddress#isAnyLocalAddress() is <code>true</code>, is returned.
 493:    *
 494:    * @return The local address
 495:    *
 496:    * @since 1.1
 497:    */
 498:   public InetAddress getLocalAddress()
 499:   {
 500:     if (! isBound())
 501:       return InetAddress.ANY_IF;
 502: 
 503:     InetAddress addr = null;
 504: 
 505:     if (impl instanceof PlainSocketImpl)
 506:       addr = ((PlainSocketImpl) impl).getLocalAddress().getAddress();
 507: 
 508:     if (addr == null)
 509:       {
 510:         try
 511:           {
 512:             addr = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
 513:           }
 514:         catch (SocketException e)
 515:           {
 516:             // (hopefully) shouldn't happen
 517:             // throw new java.lang.InternalError
 518:             //      ("Error in PlainSocketImpl.getOption");
 519:             return null;
 520:           }
 521:       }
 522: 
 523:     // FIXME: According to libgcj, checkConnect() is supposed to be called
 524:     // before performing this operation.  Problems: 1) We don't have the
 525:     // addr until after we do it, so we do a post check.  2). The docs I
 526:     // see don't require this in the Socket case, only DatagramSocket, but
 527:     // we'll assume they mean both.
 528:     SecurityManager sm = System.getSecurityManager();
 529:     if (sm != null)
 530:       sm.checkConnect(addr.getHostName(), getLocalPort());
 531: 
 532:     return addr;
 533:   }
 534: 
 535:   /**
 536:    * Returns the port number of the remote end of the socket connection.  If
 537:    * this socket is not connected, then 0 is returned.
 538:    *
 539:    * @return The remote port this socket is connected to
 540:    */
 541:   public int getPort()
 542:   {
 543:     if (! isConnected())
 544:       return 0;
 545: 
 546:     try
 547:       {
 548:         return getImpl().getPort();
 549:       }
 550:     catch (SocketException e)
 551:       {
 552:         // This cannot happen as we are connected.
 553:       }
 554: 
 555:     return 0;
 556:   }
 557: 
 558:   /**
 559:    * Returns the local port number to which this socket is bound.  If this
 560:    * socket is not connected, then -1 is returned.
 561:    *
 562:    * @return The local port
 563:    */
 564:   public int getLocalPort()
 565:   {
 566:     if (! isBound())
 567:       return -1;
 568: 
 569:     try
 570:       {
 571:         if (getImpl() != null)
 572:           return getImpl().getLocalPort();
 573:       }
 574:     catch (SocketException e)
 575:       {
 576:         // This cannot happen as we are bound.
 577:       }
 578: 
 579:     return -1;
 580:   }
 581: 
 582:   /**
 583:    * Returns local socket address.
 584:    *
 585:    * @return the local socket address, null if not bound
 586:    *
 587:    * @since 1.4
 588:    */
 589:   public SocketAddress getLocalSocketAddress()
 590:   {
 591:     if (! isBound())
 592:       return null;
 593: 
 594:     InetAddress addr = getLocalAddress();
 595: 
 596:     try
 597:       {
 598:         return new InetSocketAddress(addr, getImpl().getLocalPort());
 599:       }
 600:     catch (SocketException e)
 601:       {
 602:         // This cannot happen as we are bound.
 603:         return null;
 604:       }
 605:   }
 606: 
 607:   /**
 608:    * Returns the remote socket address.
 609:    *
 610:    * @return the remote socket address, null of not connected
 611:    *
 612:    * @since 1.4
 613:    */
 614:   public SocketAddress getRemoteSocketAddress()
 615:   {
 616:     if (! isConnected())
 617:       return null;
 618: 
 619:     try
 620:       {
 621:         return new InetSocketAddress(getImpl().getInetAddress(),
 622:                                      getImpl().getPort());
 623:       }
 624:     catch (SocketException e)
 625:       {
 626:         // This cannot happen as we are connected.
 627:         return null;
 628:       }
 629:   }
 630: 
 631:   /**
 632:    * Returns an InputStream for reading from this socket.
 633:    *
 634:    * @return The InputStream object
 635:    *
 636:    * @exception IOException If an error occurs or Socket is not connected
 637:    */
 638:   public InputStream getInputStream() throws IOException
 639:   {
 640:     if (isClosed())
 641:       throw new SocketException("socket is closed");
 642: 
 643:     if (! isConnected())
 644:       throw new IOException("not connected");
 645: 
 646:     return getImpl().getInputStream();
 647:   }
 648: 
 649:   /**
 650:    * Returns an OutputStream for writing to this socket.
 651:    *
 652:    * @return The OutputStream object
 653:    *
 654:    * @exception IOException If an error occurs or Socket is not connected
 655:    */
 656:   public OutputStream getOutputStream() throws IOException
 657:   {
 658:     if (isClosed())
 659:       throw new SocketException("socket is closed");
 660: 
 661:     if (! isConnected())
 662:       throw new IOException("not connected");
 663: 
 664:     return getImpl().getOutputStream();
 665:   }
 666: 
 667:   /**
 668:    * Sets the TCP_NODELAY option on the socket.
 669:    *
 670:    * @param on true to enable, false to disable
 671:    *
 672:    * @exception SocketException If an error occurs or Socket is not connected
 673:    *
 674:    * @since 1.1
 675:    */
 676:   public void setTcpNoDelay(boolean on) throws SocketException
 677:   {
 678:     if (isClosed())
 679:       throw new SocketException("socket is closed");
 680: 
 681:     getImpl().setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on));
 682:   }
 683: 
 684:   /**
 685:    * Tests whether or not the TCP_NODELAY option is set on the socket.
 686:    * Returns true if enabled, false if disabled. When on it disables the
 687:    * Nagle algorithm which means that packets are always send immediatly and
 688:    * never merged together to reduce network trafic.
 689:    *
 690:    * @return Whether or not TCP_NODELAY is set
 691:    *
 692:    * @exception SocketException If an error occurs or Socket not connected
 693:    *
 694:    * @since 1.1
 695:    */
 696:   public boolean getTcpNoDelay() throws SocketException
 697:   {
 698:     if (isClosed())
 699:       throw new SocketException("socket is closed");
 700: 
 701:     Object on = getImpl().getOption(SocketOptions.TCP_NODELAY);
 702: 
 703:     if (on instanceof Boolean)
 704:       return (((Boolean) on).booleanValue());
 705:     else
 706:       throw new SocketException("Internal Error");
 707:   }
 708: 
 709:   /**
 710:    * Sets the value of the SO_LINGER option on the socket.  If the
 711:    * SO_LINGER option is set on a socket and there is still data waiting to
 712:    * be sent when the socket is closed, then the close operation will block
 713:    * until either that data is delivered or until the timeout period
 714:    * expires.  The linger interval is specified in hundreths of a second
 715:    * (platform specific?)
 716:    *
 717:    * @param on true to enable SO_LINGER, false to disable
 718:    * @param linger The SO_LINGER timeout in hundreths of a second or -1 if
 719:    * SO_LINGER not set.
 720:    *
 721:    * @exception SocketException If an error occurs or Socket not connected
 722:    * @exception IllegalArgumentException If linger is negative
 723:    *
 724:    * @since 1.1
 725:    */
 726:   public void setSoLinger(boolean on, int linger) throws SocketException
 727:   {
 728:     if (isClosed())
 729:       throw new SocketException("socket is closed");
 730: 
 731:     if (on)
 732:       {
 733:         if (linger < 0)
 734:           throw new IllegalArgumentException("SO_LINGER must be >= 0");
 735: 
 736:         if (linger > 65535)
 737:           linger = 65535;
 738: 
 739:         getImpl().setOption(SocketOptions.SO_LINGER, Integer.valueOf(linger));
 740:       }
 741:     else
 742:       getImpl().setOption(SocketOptions.SO_LINGER, Integer.valueOf(-1));
 743:   }
 744: 
 745:   /**
 746:    * Returns the value of the SO_LINGER option on the socket.  If the
 747:    * SO_LINGER option is set on a socket and there is still data waiting to
 748:    * be sent when the socket is closed, then the close operation will block
 749:    * until either that data is delivered or until the timeout period
 750:    * expires.  This method either returns the timeouts (in hundredths of
 751:    * of a second (platform specific?)) if SO_LINGER is set, or -1 if
 752:    * SO_LINGER is not set.
 753:    *
 754:    * @return The SO_LINGER timeout in hundreths of a second or -1
 755:    * if SO_LINGER not set
 756:    *
 757:    * @exception SocketException If an error occurs or Socket is not connected
 758:    *
 759:    * @since 1.1
 760:    */
 761:   public int getSoLinger() throws SocketException
 762:   {
 763:     if (isClosed())
 764:       throw new SocketException("socket is closed");
 765: 
 766:     Object linger = getImpl().getOption(SocketOptions.SO_LINGER);
 767: 
 768:     if (linger instanceof Integer)
 769:       return (((Integer) linger).intValue());
 770:     else
 771:       return -1;
 772:   }
 773: 
 774:   /**
 775:    * Sends urgent data through the socket
 776:    *
 777:    * @param data The data to send.
 778:    * Only the lowest eight bits of data are sent
 779:    *
 780:    * @exception IOException If an error occurs
 781:    *
 782:    * @since 1.4
 783:    */
 784:   public void sendUrgentData(int data) throws IOException
 785:   {
 786:     if (isClosed())
 787:       throw new SocketException("socket is closed");
 788: 
 789:     getImpl().sendUrgentData(data);
 790:   }
 791: 
 792:   /**
 793:    * Enables/disables the SO_OOBINLINE option
 794:    *
 795:    * @param on True if SO_OOBLINE should be enabled
 796:    *
 797:    * @exception SocketException If an error occurs
 798:    *
 799:    * @since 1.4
 800:    */
 801:   public void setOOBInline(boolean on) throws SocketException
 802:   {
 803:     if (isClosed())
 804:       throw new SocketException("socket is closed");
 805: 
 806:     getImpl().setOption(SocketOptions.SO_OOBINLINE, Boolean.valueOf(on));
 807:   }
 808: 
 809:   /**
 810:    * Returns the current setting of the SO_OOBINLINE option for this socket
 811:    *
 812:    * @return True if SO_OOBINLINE is set, false otherwise.
 813:    *
 814:    * @exception SocketException If an error occurs
 815:    *
 816:    * @since 1.4
 817:    */
 818:   public boolean getOOBInline() throws SocketException
 819:   {
 820:     if (isClosed())
 821:       throw new SocketException("socket is closed");
 822: 
 823:     Object buf = getImpl().getOption(SocketOptions.SO_OOBINLINE);
 824: 
 825:     if (buf instanceof Boolean)
 826:       return (((Boolean) buf).booleanValue());
 827:     else
 828:       throw new SocketException("Internal Error: Unexpected type");
 829:   }
 830: 
 831:   /**
 832:    * Sets the value of the SO_TIMEOUT option on the socket.  If this value
 833:    * is set, and an read/write is performed that does not complete within
 834:    * the timeout period, a short count is returned (or an EWOULDBLOCK signal
 835:    * would be sent in Unix if no data had been read).  A value of 0 for
 836:    * this option implies that there is no timeout (ie, operations will
 837:    * block forever).  On systems that have separate read and write timeout
 838:    * values, this method returns the read timeout.  This
 839:    * value is in milliseconds.
 840:    *
 841:    * @param timeout The length of the timeout in milliseconds, or
 842:    * 0 to indicate no timeout.
 843:    *
 844:    * @exception SocketException If an error occurs or Socket not connected
 845:    *
 846:    * @since 1.1
 847:    */
 848:   public synchronized void setSoTimeout(int timeout) throws SocketException
 849:   {
 850:     if (isClosed())
 851:       throw new SocketException("socket is closed");
 852: 
 853:     if (timeout < 0)
 854:       throw new IllegalArgumentException("SO_TIMEOUT value must be >= 0");
 855: 
 856:     getImpl().setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout));
 857:   }
 858: 
 859:   /**
 860:    * Returns the value of the SO_TIMEOUT option on the socket.  If this value
 861:    * is set, and an read/write is performed that does not complete within
 862:    * the timeout period, a short count is returned (or an EWOULDBLOCK signal
 863:    * would be sent in Unix if no data had been read).  A value of 0 for
 864:    * this option implies that there is no timeout (ie, operations will
 865:    * block forever).  On systems that have separate read and write timeout
 866:    * values, this method returns the read timeout.  This
 867:    * value is in thousandths of a second (implementation specific?).
 868:    *
 869:    * @return The length of the timeout in thousandth's of a second or 0
 870:    * if not set
 871:    *
 872:    * @exception SocketException If an error occurs or Socket not connected
 873:    *
 874:    * @since 1.1
 875:    */
 876:   public synchronized int getSoTimeout() throws SocketException
 877:   {
 878:     if (isClosed())
 879:       throw new SocketException("socket is closed");
 880: 
 881:     Object timeout = getImpl().getOption(SocketOptions.SO_TIMEOUT);
 882:     if (timeout instanceof Integer)
 883:       return (((Integer) timeout).intValue());
 884:     else
 885:       return 0;
 886:   }
 887: 
 888:   /**
 889:    * This method sets the value for the system level socket option
 890:    * SO_SNDBUF to the specified value.  Note that valid values for this
 891:    * option are specific to a given operating system.
 892:    *
 893:    * @param size The new send buffer size.
 894:    *
 895:    * @exception SocketException If an error occurs or Socket not connected
 896:    * @exception IllegalArgumentException If size is 0 or negative
 897:    *
 898:    * @since 1.2
 899:    */
 900:   public void setSendBufferSize(int size) throws SocketException
 901:   {
 902:     if (isClosed())
 903:       throw new SocketException("socket is closed");
 904: 
 905:     if (size <= 0)
 906:       throw new IllegalArgumentException("SO_SNDBUF value must be > 0");
 907: 
 908:     getImpl().setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size));
 909:   }
 910: 
 911:   /**
 912:    * This method returns the value of the system level socket option
 913:    * SO_SNDBUF, which is used by the operating system to tune buffer
 914:    * sizes for data transfers.
 915:    *
 916:    * @return The send buffer size.
 917:    *
 918:    * @exception SocketException If an error occurs or socket not connected
 919:    *
 920:    * @since 1.2
 921:    */
 922:   public int getSendBufferSize() throws SocketException
 923:   {
 924:     if (isClosed())
 925:       throw new SocketException("socket is closed");
 926: 
 927:     Object buf = getImpl().getOption(SocketOptions.SO_SNDBUF);
 928: 
 929:     if (buf instanceof Integer)
 930:       return (((Integer) buf).intValue());
 931:     else
 932:       throw new SocketException("Internal Error: Unexpected type");
 933:   }
 934: 
 935:   /**
 936:    * This method sets the value for the system level socket option
 937:    * SO_RCVBUF to the specified value.  Note that valid values for this
 938:    * option are specific to a given operating system.
 939:    *
 940:    * @param size The new receive buffer size.
 941:    *
 942:    * @exception SocketException If an error occurs or Socket is not connected
 943:    * @exception IllegalArgumentException If size is 0 or negative
 944:    *
 945:    * @since 1.2
 946:    */
 947:   public void setReceiveBufferSize(int size) throws SocketException
 948:   {
 949:     if (isClosed())
 950:       throw new SocketException("socket is closed");
 951: 
 952:     if (size <= 0)
 953:       throw new IllegalArgumentException("SO_RCVBUF value must be > 0");
 954: 
 955:     getImpl().setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
 956:   }
 957: 
 958:   /**
 959:    * This method returns the value of the system level socket option
 960:    * SO_RCVBUF, which is used by the operating system to tune buffer
 961:    * sizes for data transfers.
 962:    *
 963:    * @return The receive buffer size.
 964:    *
 965:    * @exception SocketException If an error occurs or Socket is not connected
 966:    *
 967:    * @since 1.2
 968:    */
 969:   public int getReceiveBufferSize() throws SocketException
 970:   {
 971:     if (isClosed())
 972:       throw new SocketException("socket is closed");
 973: 
 974:     Object buf = getImpl().getOption(SocketOptions.SO_RCVBUF);
 975: 
 976:     if (buf instanceof Integer)
 977:       return (((Integer) buf).intValue());
 978:     else
 979:       throw new SocketException("Internal Error: Unexpected type");
 980:   }
 981: 
 982:   /**
 983:    * This method sets the value for the socket level socket option
 984:    * SO_KEEPALIVE.
 985:    *
 986:    * @param on True if SO_KEEPALIVE should be enabled
 987:    *
 988:    * @exception SocketException If an error occurs or Socket is not connected
 989:    *
 990:    * @since 1.3
 991:    */
 992:   public void setKeepAlive(boolean on) throws SocketException
 993:   {
 994:     if (isClosed())
 995:       throw new SocketException("socket is closed");
 996: 
 997:     getImpl().setOption(SocketOptions.SO_KEEPALIVE, Boolean.valueOf(on));
 998:   }
 999: 
1000:   /**
1001:    * This method returns the value of the socket level socket option
1002:    * SO_KEEPALIVE.
1003:    *
1004:    * @return The setting
1005:    *
1006:    * @exception SocketException If an error occurs or Socket is not connected
1007:    *
1008:    * @since 1.3
1009:    */
1010:   public boolean getKeepAlive() throws SocketException
1011:   {
1012:     if (isClosed())
1013:       throw new SocketException("socket is closed");
1014: 
1015:     Object buf = getImpl().getOption(SocketOptions.SO_KEEPALIVE);
1016: 
1017:     if (buf instanceof Boolean)
1018:       return (((Boolean) buf).booleanValue());
1019:     else
1020:       throw new SocketException("Internal Error: Unexpected type");
1021:   }
1022: 
1023:   /**
1024:    * Closes the socket.
1025:    *
1026:    * @exception IOException If an error occurs
1027:    */
1028:   public synchronized void close() throws IOException
1029:   {
1030:     if (isClosed())
1031:       return;
1032: 
1033:     impl.close();
1034:     impl = null;
1035:   }
1036: 
1037:   /**
1038:    * Converts this <code>Socket</code> to a <code>String</code>.
1039:    *
1040:    * @return The <code>String</code> representation of this <code>Socket</code>
1041:    */
1042:   public String toString()
1043:   {
1044:     try
1045:       {
1046:         if (isConnected())
1047:           return (super.toString()
1048:                   + " [addr=" + getImpl().getInetAddress() + ",port="
1049:                   + getImpl().getPort() + ",localport="
1050:                   + getImpl().getLocalPort() + "]");
1051:       }
1052:     catch (SocketException e)
1053:       {
1054:         // This cannot happen as we are connected.
1055:       }
1056: 
1057:     return super.toString() + " [unconnected]";
1058:   }
1059: 
1060:   /**
1061:    * Sets the <code>SocketImplFactory</code>.  This may be done only once per
1062:    * virtual machine.  Subsequent attempts will generate a
1063:    * <code>SocketException</code>.  Note that a <code>SecurityManager</code>
1064:    * check is made prior to setting the factory.  If
1065:    * insufficient privileges exist to set the factory, then an
1066:    * <code>IOException</code> will be thrown.
1067:    *
1068:    * @param fac the factory to set
1069:    *
1070:    * @exception SecurityException If the <code>SecurityManager</code> does
1071:    * not allow this operation.
1072:    * @exception SocketException If the SocketImplFactory is already defined
1073:    * @exception IOException If any other error occurs
1074:    */
1075:   public static synchronized void setSocketImplFactory(SocketImplFactory fac)
1076:     throws IOException
1077:   {
1078:     // See if already set
1079:     if (factory != null)
1080:       throw new SocketException("SocketImplFactory already defined");
1081: 
1082:     // Check permissions
1083:     SecurityManager sm = System.getSecurityManager();
1084:     if (sm != null)
1085:       sm.checkSetFactory();
1086: 
1087:     if (fac == null)
1088:       throw new SocketException("SocketImplFactory cannot be null");
1089: 
1090:     factory = fac;
1091:   }
1092: 
1093:   /**
1094:    * Closes the input side of the socket stream.
1095:    *
1096:    * @exception IOException If an error occurs.
1097:    *
1098:    * @since 1.3
1099:    */
1100:   public void shutdownInput() throws IOException
1101:   {
1102:     if (isClosed())
1103:       throw new SocketException("socket is closed");
1104: 
1105:     getImpl().shutdownInput();
1106:     inputShutdown = true;
1107:   }
1108: 
1109:   /**
1110:    * Closes the output side of the socket stream.
1111:    *
1112:    * @exception IOException If an error occurs.
1113:    *
1114:    * @since 1.3
1115:    */
1116:   public void shutdownOutput() throws IOException
1117:   {
1118:     if (isClosed())
1119:       throw new SocketException("socket is closed");
1120: 
1121:     getImpl().shutdownOutput();
1122:     outputShutdown = true;
1123:   }
1124: 
1125:   /**
1126:    * Returns the socket channel associated with this socket.
1127:    *
1128:    * @return the associated socket channel,
1129:    * null if no associated channel exists
1130:    *
1131:    * @since 1.4
1132:    */
1133:   public SocketChannel getChannel()
1134:   {
1135:     return null;
1136:   }
1137: 
1138:   /**
1139:    * Checks if the SO_REUSEADDR option is enabled
1140:    *
1141:    * @return True if SO_REUSEADDR is set, false otherwise.
1142:    *
1143:    * @exception SocketException If an error occurs
1144:    *
1145:    * @since 1.4
1146:    */
1147:   public boolean getReuseAddress() throws SocketException
1148:   {
1149:     if (isClosed())
1150:       throw new SocketException("socket is closed");
1151: 
1152:     Object reuseaddr = getImpl().getOption(SocketOptions.SO_REUSEADDR);
1153: 
1154:     if (! (reuseaddr instanceof Boolean))
1155:       throw new SocketException("Internal Error");
1156: 
1157:     return ((Boolean) reuseaddr).booleanValue();
1158:   }
1159: 
1160:   /**
1161:    * Enables/Disables the SO_REUSEADDR option
1162:    *
1163:    * @param reuseAddress true if SO_REUSEADDR should be enabled,
1164:    * false otherwise
1165:    *
1166:    * @exception SocketException If an error occurs
1167:    *
1168:    * @since 1.4
1169:    */
1170:   public void setReuseAddress(boolean reuseAddress) throws SocketException
1171:   {
1172:     if (isClosed())
1173:       throw new SocketException("socket is closed");
1174: 
1175:     getImpl().setOption(SocketOptions.SO_REUSEADDR,
1176:                         Boolean.valueOf(reuseAddress));
1177:   }
1178: 
1179:   /**
1180:    * Returns the current traffic class
1181:    *
1182:    * @return The current traffic class.
1183:    *
1184:    * @exception SocketException If an error occurs
1185:    *
1186:    * @see Socket#setTrafficClass(int tc)
1187:    *
1188:    * @since 1.4
1189:    */
1190:   public int getTrafficClass() throws SocketException
1191:   {
1192:     if (isClosed())
1193:       throw new SocketException("socket is closed");
1194: 
1195:     Object obj = getImpl().getOption(SocketOptions.IP_TOS);
1196: 
1197:     if (obj instanceof Integer)
1198:       return ((Integer) obj).intValue();
1199:     else
1200:       throw new SocketException("Unexpected type");
1201:   }
1202: 
1203:   /**
1204:    * Sets the traffic class value
1205:    *
1206:    * @param tc The traffic class
1207:    *
1208:    * @exception SocketException If an error occurs
1209:    * @exception IllegalArgumentException If tc value is illegal
1210:    *
1211:    * @see Socket#getTrafficClass()
1212:    *
1213:    * @since 1.4
1214:    */
1215:   public void setTrafficClass(int tc) throws SocketException
1216:   {
1217:     if (isClosed())
1218:       throw new SocketException("socket is closed");
1219: 
1220:     if (tc < 0 || tc > 255)
1221:       throw new IllegalArgumentException();
1222: 
1223:     getImpl().setOption(SocketOptions.IP_TOS, Integer.valueOf(tc));
1224:   }
1225: 
1226:   /**
1227:    * Checks if the socket is connected
1228:    *
1229:    * @return True if socket is connected, false otherwise.
1230:    *
1231:    * @since 1.4
1232:    */
1233:   public boolean isConnected()
1234:   {
1235:     if (impl == null)
1236:       return false;
1237: 
1238:     return impl.getInetAddress() != null;
1239:   }
1240: 
1241:   /**
1242:    * Checks if the socket is already bound.
1243:    *
1244:    * @return True if socket is bound, false otherwise.
1245:    *
1246:    * @since 1.4
1247:    */
1248:   public boolean isBound()
1249:   {
1250:     if (isClosed())
1251:       return false;
1252:     if (impl instanceof PlainSocketImpl)
1253:       {
1254:         InetSocketAddress addr = ((PlainSocketImpl) impl).getLocalAddress();
1255:         return addr != null && addr.getAddress() != null;
1256:       }
1257:     return bound;
1258:   }
1259: 
1260:   /**
1261:    * Checks if the socket is closed.
1262:    *
1263:    * @return True if socket is closed, false otherwise.
1264:    *
1265:    * @since 1.4
1266:    */
1267:   public boolean isClosed()
1268:   {
1269:     SocketChannel channel = getChannel();
1270: 
1271:     return impl == null || (channel != null && ! channel.isOpen());
1272:   }
1273: 
1274:   /**
1275:    * Checks if the socket's input stream is shutdown
1276:    *
1277:    * @return True if input is shut down.
1278:    *
1279:    * @since 1.4
1280:    */
1281:   public boolean isInputShutdown()
1282:   {
1283:     return inputShutdown;
1284:   }
1285: 
1286:   /**
1287:    * Checks if the socket's output stream is shutdown
1288:    *
1289:    * @return True if output is shut down.
1290:    *
1291:    * @since 1.4
1292:    */
1293:   public boolean isOutputShutdown()
1294:   {
1295:     return outputShutdown;
1296:   }
1297: }