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