Source for java.net.ServerSocket

   1: /* ServerSocket.java -- Class for implementing server side sockets
   2:    Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2006
   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.nio.channels.IllegalBlockingModeException;
  45: import java.nio.channels.ServerSocketChannel;
  46: 
  47: 
  48: /* Written using on-line Java Platform 1.2 API Specification.
  49:  * Status:  I believe all methods are implemented.
  50:  */
  51: 
  52: /**
  53:  * This class models server side sockets.  The basic model is that the
  54:  * server socket is created and bound to some well known port.  It then
  55:  * listens for and accepts connections.  At that point the client and
  56:  * server sockets are ready to communicate with one another utilizing
  57:  * whatever application layer protocol they desire.
  58:  *
  59:  * As with the <code>Socket</code> class, most instance methods of this class
  60:  * simply redirect their calls to an implementation class.
  61:  *
  62:  * @author Aaron M. Renn (arenn@urbanophile.com)
  63:  * @author Per Bothner (bothner@cygnus.com)
  64:  */
  65: public class ServerSocket
  66: {
  67:   /**
  68:    * This is the user defined SocketImplFactory, if one is supplied
  69:    */
  70:   private static SocketImplFactory factory;
  71: 
  72:   /**
  73:    * This is the SocketImp object to which most instance methods in this
  74:    * class are redirected
  75:    */
  76:   private SocketImpl impl;
  77: 
  78:   /**
  79:    * We need to retain the local address even after the socket is closed.
  80:    */
  81:   private InetSocketAddress local;
  82: 
  83:   /*
  84:    * This constructor is only used by java.nio.
  85:    */
  86: 
  87:   // FIXME: Workaround a bug in gcj.
  88:   //ServerSocket (PlainSocketImpl impl) throws IOException
  89:   ServerSocket(SocketImpl impl) throws IOException
  90:   {
  91:     if (impl == null)
  92:       throw new NullPointerException("impl may not be null");
  93: 
  94:     this.impl = impl;
  95:     this.impl.create(true);
  96:   }
  97: 
  98:   /*
  99:    * This method is only used by java.nio.
 100:    */
 101: 
 102:   // FIXME: Workaround a bug in gcj.
 103:   //PlainSocketImpl getImpl()
 104:   SocketImpl getImpl()
 105:   {
 106:     return impl;
 107:   }
 108: 
 109:   /**
 110:    * Constructor that simply sets the implementation.
 111:    *
 112:    * @exception IOException If an error occurs
 113:    *
 114:    * @specnote This constructor is public since JDK 1.4
 115:    */
 116:   public ServerSocket() throws IOException
 117:   {
 118:     if (factory != null)
 119:       impl = factory.createSocketImpl();
 120:     else
 121:       impl = new PlainSocketImpl();
 122: 
 123:     impl.create(true);
 124:   }
 125: 
 126:   /**
 127:    * Creates a server socket and binds it to the specified port.  If the
 128:    * port number is 0, a random free port will be chosen.  The pending
 129:    * connection queue on this socket will be set to 50.
 130:    *
 131:    * @param port The port number to bind to
 132:    *
 133:    * @exception IOException If an error occurs
 134:    * @exception SecurityException If a security manager exists and its
 135:    * checkListen method doesn't allow the operation
 136:    */
 137:   public ServerSocket(int port) throws IOException
 138:   {
 139:     this(port, 50);
 140:   }
 141: 
 142:   /**
 143:    * Creates a server socket and binds it to the specified port.  If the
 144:    * port number is 0, a random free port will be chosen.  The pending
 145:    * connection queue on this socket will be set to the value passed as
 146:    * arg2.
 147:    *
 148:    * @param port The port number to bind to
 149:    * @param backlog The length of the pending connection queue
 150:    *
 151:    * @exception IOException If an error occurs
 152:    * @exception SecurityException If a security manager exists and its
 153:    * checkListen method doesn't allow the operation
 154:    */
 155:   public ServerSocket(int port, int backlog) throws IOException
 156:   {
 157:     this(port, backlog, null);
 158:   }
 159: 
 160:   /**
 161:    * Creates a server socket and binds it to the specified port.  If the
 162:    * port number is 0, a random free port will be chosen.  The pending
 163:    * connection queue on this socket will be set to the value passed as
 164:    * backlog.  The third argument specifies a particular local address to
 165:    * bind t or null to bind to all local address.
 166:    *
 167:    * @param port The port number to bind to
 168:    * @param backlog The length of the pending connection queue
 169:    * @param bindAddr The address to bind to, or null to bind to all addresses
 170:    *
 171:    * @exception IOException If an error occurs
 172:    * @exception SecurityException If a security manager exists and its
 173:    * checkListen method doesn't allow the operation
 174:    *
 175:    * @since 1.1
 176:    */
 177:   public ServerSocket(int port, int backlog, InetAddress bindAddr)
 178:     throws IOException
 179:   {
 180:     this();
 181: 
 182:     // bind/listen socket
 183:     bind(new InetSocketAddress(bindAddr, port), backlog);
 184:   }
 185: 
 186:   /**
 187:    * Binds the server socket to a specified socket address
 188:    *
 189:    * @param endpoint The socket address to bind to
 190:    *
 191:    * @exception IOException If an error occurs
 192:    * @exception IllegalArgumentException If address type is not supported
 193:    * @exception SecurityException If a security manager exists and its
 194:    * checkListen method doesn't allow the operation
 195:    *
 196:    * @since 1.4
 197:    */
 198:   public void bind(SocketAddress endpoint) throws IOException
 199:   {
 200:     bind(endpoint, 50);
 201:   }
 202: 
 203:   /**
 204:    * Binds the server socket to a specified socket address
 205:    *
 206:    * @param endpoint The socket address to bind to
 207:    * @param backlog The length of the pending connection queue
 208:    *
 209:    * @exception IOException If an error occurs
 210:    * @exception IllegalArgumentException If address type is not supported
 211:    * @exception SecurityException If a security manager exists and its
 212:    * checkListen method doesn't allow the operation
 213:    *
 214:    * @since 1.4
 215:    */
 216:   public void bind(SocketAddress endpoint, int backlog)
 217:     throws IOException
 218:   {
 219:     if (isClosed())
 220:       throw new SocketException("ServerSocket is closed");
 221: 
 222:     if (! (endpoint instanceof InetSocketAddress))
 223:       throw new IllegalArgumentException("Address type not supported");
 224: 
 225:     InetSocketAddress tmp = (InetSocketAddress) endpoint;
 226: 
 227:     SecurityManager s = System.getSecurityManager();
 228:     if (s != null)
 229:       s.checkListen(tmp.getPort());
 230: 
 231:     InetAddress addr = tmp.getAddress();
 232: 
 233:     // Initialize addr with 0.0.0.0.
 234:     if (addr == null)
 235:       addr = InetAddress.ANY_IF;
 236: 
 237:     try
 238:       {
 239:     impl.bind(addr, tmp.getPort());
 240:     impl.listen(backlog);
 241:     local = new InetSocketAddress(
 242:             (InetAddress) impl.getOption(SocketOptions.SO_BINDADDR),
 243:             impl.getLocalPort());
 244:       }
 245:     catch (IOException exception)
 246:       {
 247:     close();
 248:     throw exception;
 249:       }
 250:     catch (RuntimeException exception)
 251:       {
 252:     close();
 253:     throw exception;
 254:       }
 255:     catch (Error error)
 256:       {
 257:     close();
 258:     throw error;
 259:       }
 260:   }
 261: 
 262:   /**
 263:    * This method returns the local address to which this socket is bound
 264:    *
 265:    * @return The socket's local address
 266:    */
 267:   public InetAddress getInetAddress()
 268:   {
 269:     if (local == null)
 270:       return null;
 271: 
 272:     return local.getAddress();
 273:   }
 274: 
 275:   /**
 276:    * This method returns the local port number to which this socket is bound
 277:    *
 278:    * @return The socket's port number
 279:    */
 280:   public int getLocalPort()
 281:   {
 282:     if (local == null)
 283:       return -1;
 284: 
 285:     return local.getPort();
 286:   }
 287: 
 288:   /**
 289:    * Returns the local socket address
 290:    *
 291:    * @return the local socket address, null if not bound
 292:    * 
 293:    * @since 1.4
 294:    */
 295:   public SocketAddress getLocalSocketAddress()
 296:   {
 297:     return local;
 298:   }
 299: 
 300:   /**
 301:    * Accepts a new connection and returns a connected <code>Socket</code>
 302:    * instance representing that connection.  This method will block until a
 303:    * connection is available.
 304:    *
 305:    * @return socket object for the just accepted connection
 306:    *
 307:    * @exception IOException If an error occurs
 308:    * @exception SecurityException If a security manager exists and its
 309:    * checkListen method doesn't allow the operation
 310:    * @exception IllegalBlockingModeException If this socket has an associated
 311:    * channel, and the channel is in non-blocking mode
 312:    * @exception SocketTimeoutException If a timeout was previously set with
 313:    * setSoTimeout and the timeout has been reached
 314:    */
 315:   public Socket accept() throws IOException
 316:   {
 317:     Socket socket = new Socket();
 318: 
 319:     try
 320:       {
 321:     implAccept(socket);
 322:       }
 323:     catch (IOException e)
 324:       {
 325:     try
 326:       {
 327:         socket.close();
 328:       }
 329:     catch (IOException e2)
 330:       {
 331:         // Ignore.
 332:       }
 333: 
 334:     throw e;
 335:       }
 336: 
 337:     return socket;
 338:   }
 339: 
 340:   /**
 341:    * This protected method is used to help subclasses override
 342:    * <code>ServerSocket.accept()</code>.  The passed in socket will be
 343:    * connected when this method returns.
 344:    *
 345:    * @param socket The socket that is used for the accepted connection
 346:    *
 347:    * @exception IOException If an error occurs
 348:    * @exception IllegalBlockingModeException If this socket has an associated
 349:    * channel, and the channel is in non-blocking mode
 350:    *
 351:    * @since 1.1
 352:    */
 353:   protected final void implAccept(Socket socket) throws IOException
 354:   {
 355:     if (isClosed())
 356:       throw new SocketException("ServerSocket is closed");
 357: 
 358:     // FIXME: Add a security check to make sure we're allowed to 
 359:     // connect to the remote host.
 360: 
 361:     // The Sun spec says that if we have an associated channel and
 362:     // it is in non-blocking mode, we throw an IllegalBlockingModeException.
 363:     // However, in our implementation if the channel itself initiated this
 364:     // operation, then we must honor it regardless of its blocking mode.
 365:     if (getChannel() != null && ! getChannel().isBlocking()
 366:         && ! ((PlainSocketImpl) getImpl()).isInChannelOperation())
 367:       throw new IllegalBlockingModeException();
 368: 
 369:     impl.accept(socket.impl);
 370:     socket.implCreated = true;
 371:     socket.bound = true;
 372:   }
 373: 
 374:   /**
 375:    * Closes this socket and stops listening for connections
 376:    *
 377:    * @exception IOException If an error occurs
 378:    */
 379:   public void close() throws IOException
 380:   {
 381:     if (isClosed())
 382:       return;
 383: 
 384:     impl.close();
 385:     impl = null;
 386: 
 387:     if (getChannel() != null)
 388:       getChannel().close();
 389:   }
 390: 
 391:   /**
 392:    * Returns the unique <code>ServerSocketChannel</code> object
 393:    * associated with this socket, if any.
 394:    *
 395:    * <p>The socket only has a <code>ServerSocketChannel</code> if its created
 396:    * by <code>ServerSocketChannel.open()</code>.</p>
 397:    *
 398:    * @return the associated socket channel, null if none exists
 399:    * 
 400:    * @since 1.4
 401:    */
 402:   public ServerSocketChannel getChannel()
 403:   {
 404:     return null;
 405:   }
 406: 
 407:   /**
 408:    * Returns true when the socket is bound, otherwise false
 409:    *
 410:    * @return true if socket is bound, false otherwise
 411:    * 
 412:    * @since 1.4
 413:    */
 414:   public boolean isBound()
 415:   {
 416:     return local != null;
 417:   }
 418: 
 419:   /**
 420:    * Returns true if the socket is closed, otherwise false
 421:    *
 422:    * @return true if socket is closed, false otherwise
 423:    * 
 424:    * @since 1.4
 425:    */
 426:   public boolean isClosed()
 427:   {
 428:     return impl == null;
 429:   }
 430: 
 431:   /**
 432:    * Sets the value of SO_TIMEOUT.  A value of 0 implies that SO_TIMEOUT is
 433:    * disabled (ie, operations never time out).  This is the number of
 434:    * milliseconds a socket operation can block before an
 435:    * InterruptedIOException is thrown.
 436:    *
 437:    * @param timeout The new SO_TIMEOUT value
 438:    *
 439:    * @exception SocketException If an error occurs
 440:    *
 441:    * @since 1.1
 442:    */
 443:   public void setSoTimeout(int timeout) throws SocketException
 444:   {
 445:     if (isClosed())
 446:       throw new SocketException("ServerSocket is closed");
 447: 
 448:     if (timeout < 0)
 449:       throw new IllegalArgumentException("SO_TIMEOUT value must be >= 0");
 450: 
 451:     impl.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
 452:   }
 453: 
 454:   /**
 455:    * Retrieves the current value of the SO_TIMEOUT setting.  A value of 0
 456:    * implies that SO_TIMEOUT is disabled (ie, operations never time out).
 457:    * This is the number of milliseconds a socket operation can block before
 458:    * an InterruptedIOException is thrown.
 459:    *
 460:    * @return The value of SO_TIMEOUT
 461:    *
 462:    * @exception IOException If an error occurs
 463:    *
 464:    * @since 1.1
 465:    */
 466:   public int getSoTimeout() throws IOException
 467:   {
 468:     if (isClosed())
 469:       throw new SocketException("ServerSocket is closed");
 470: 
 471:     Object timeout = impl.getOption(SocketOptions.SO_TIMEOUT);
 472: 
 473:     if (! (timeout instanceof Integer))
 474:       throw new IOException("Internal Error");
 475: 
 476:     return ((Integer) timeout).intValue();
 477:   }
 478: 
 479:   /**
 480:    * Enables/Disables the SO_REUSEADDR option
 481:    *
 482:    * @param on true if SO_REUSEADDR should be enabled, false otherwise
 483:    * 
 484:    * @exception SocketException If an error occurs
 485:    *
 486:    * @since 1.4
 487:    */
 488:   public void setReuseAddress(boolean on) throws SocketException
 489:   {
 490:     if (isClosed())
 491:       throw new SocketException("ServerSocket is closed");
 492: 
 493:     impl.setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on));
 494:   }
 495: 
 496:   /**
 497:    * Checks if the SO_REUSEADDR option is enabled
 498:    *
 499:    * @return true if SO_REUSEADDR is set, false otherwise
 500:    *
 501:    * @exception SocketException If an error occurs
 502:    *
 503:    * @since 1.4
 504:    */
 505:   public boolean getReuseAddress() throws SocketException
 506:   {
 507:     if (isClosed())
 508:       throw new SocketException("ServerSocket is closed");
 509: 
 510:     Object reuseaddr = impl.getOption(SocketOptions.SO_REUSEADDR);
 511: 
 512:     if (! (reuseaddr instanceof Boolean))
 513:       throw new SocketException("Internal Error");
 514: 
 515:     return ((Boolean) reuseaddr).booleanValue();
 516:   }
 517: 
 518:   /**
 519:    * This method sets the value for the system level socket option
 520:    * SO_RCVBUF to the specified value.  Note that valid values for this
 521:    * option are specific to a given operating system.
 522:    *
 523:    * @param size The new receive buffer size.
 524:    *
 525:    * @exception SocketException If an error occurs or Socket is not connected
 526:    * @exception IllegalArgumentException If size is 0 or negative
 527:    *
 528:    * @since 1.4
 529:    */
 530:   public void setReceiveBufferSize(int size) throws SocketException
 531:   {
 532:     if (isClosed())
 533:       throw new SocketException("ServerSocket is closed");
 534: 
 535:     if (size <= 0)
 536:       throw new IllegalArgumentException("SO_RCVBUF value must be > 0");
 537: 
 538:     impl.setOption(SocketOptions.SO_RCVBUF, new Integer(size));
 539:   }
 540: 
 541:   /**
 542:    * This method returns the value of the system level socket option
 543:    * SO_RCVBUF, which is used by the operating system to tune buffer
 544:    * sizes for data transfers.
 545:    *
 546:    * @return The receive buffer size.
 547:    *
 548:    * @exception SocketException If an error occurs or Socket is not connected
 549:    *
 550:    * @since 1.4
 551:    */
 552:   public int getReceiveBufferSize() throws SocketException
 553:   {
 554:     if (isClosed())
 555:       throw new SocketException("ServerSocket is closed");
 556: 
 557:     Object buf = impl.getOption(SocketOptions.SO_RCVBUF);
 558: 
 559:     if (! (buf instanceof Integer))
 560:       throw new SocketException("Internal Error: Unexpected type");
 561: 
 562:     return ((Integer) buf).intValue();
 563:   }
 564: 
 565:   /**
 566:    * Returns the value of this socket as a <code>String</code>.
 567:    *
 568:    * @return This socket represented as a <code>String</code>.
 569:    */
 570:   public String toString()
 571:   {
 572:     if (! isBound())
 573:       return "ServerSocket[unbound]";
 574: 
 575:     return ("ServerSocket[addr=" + getInetAddress() + ",port="
 576:            + impl.getPort() + ",localport=" + impl.getLocalPort() + "]");
 577:   }
 578: 
 579:   /**
 580:    * Sets the <code>SocketImplFactory</code> for all
 581:    * <code>ServerSocket</code>'s.  This may only be done
 582:    * once per virtual machine.  Subsequent attempts will generate an
 583:    * exception.  Note that a <code>SecurityManager</code> check is made prior
 584:    * to setting the factory.  If insufficient privileges exist to set the
 585:    * factory, an exception will be thrown
 586:    *
 587:    * @param fac the factory to set
 588:    *
 589:    * @exception SecurityException If this operation is not allowed by the
 590:    * <code>SecurityManager</code>.
 591:    * @exception SocketException If the factory object is already defined
 592:    * @exception IOException If any other error occurs
 593:    */
 594:   public static synchronized void setSocketFactory(SocketImplFactory fac)
 595:     throws IOException
 596:   {
 597:     factory = fac;
 598:   }
 599: }