Frames | No Frames |
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: }