001/* ServerSocket.java -- Class for implementing server side sockets 002 Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2006 003 Free Software Foundation, Inc. 004 005This file is part of GNU Classpath. 006 007GNU Classpath is free software; you can redistribute it and/or modify 008it under the terms of the GNU General Public License as published by 009the Free Software Foundation; either version 2, or (at your option) 010any later version. 011 012GNU Classpath is distributed in the hope that it will be useful, but 013WITHOUT ANY WARRANTY; without even the implied warranty of 014MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015General Public License for more details. 016 017You should have received a copy of the GNU General Public License 018along with GNU Classpath; see the file COPYING. If not, write to the 019Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02002110-1301 USA. 021 022Linking this library statically or dynamically with other modules is 023making a combined work based on this library. Thus, the terms and 024conditions of the GNU General Public License cover the whole 025combination. 026 027As a special exception, the copyright holders of this library give you 028permission to link this library with independent modules to produce an 029executable, regardless of the license terms of these independent 030modules, and to copy and distribute the resulting executable under 031terms of your choice, provided that you also meet, for each linked 032independent module, the terms and conditions of the license of that 033module. An independent module is a module which is not derived from 034or based on this library. If you modify this library, you may extend 035this exception to your version of the library, but you are not 036obligated to do so. If you do not wish to do so, delete this 037exception statement from your version. */ 038 039package java.net; 040 041import gnu.java.net.PlainSocketImpl; 042 043import java.io.IOException; 044import java.nio.channels.IllegalBlockingModeException; 045import java.nio.channels.ServerSocketChannel; 046 047 048/* Written using on-line Java Platform 1.2 API Specification. 049 * Status: I believe all methods are implemented. 050 */ 051 052/** 053 * This class models server side sockets. The basic model is that the 054 * server socket is created and bound to some well known port. It then 055 * listens for and accepts connections. At that point the client and 056 * server sockets are ready to communicate with one another utilizing 057 * whatever application layer protocol they desire. 058 * 059 * As with the <code>Socket</code> class, most instance methods of this class 060 * simply redirect their calls to an implementation class. 061 * 062 * @author Aaron M. Renn (arenn@urbanophile.com) 063 * @author Per Bothner (bothner@cygnus.com) 064 */ 065public class ServerSocket 066{ 067 /** 068 * This is the user defined SocketImplFactory, if one is supplied 069 */ 070 private static SocketImplFactory factory; 071 072 /** 073 * This is the SocketImp object to which most instance methods in this 074 * class are redirected 075 */ 076 private SocketImpl impl; 077 078 /** 079 * We need to retain the local address even after the socket is closed. 080 */ 081 private InetSocketAddress local; 082 private int port; 083 084 /* 085 * This constructor is only used by java.nio. 086 */ 087 088 ServerSocket(PlainSocketImpl impl) throws IOException 089 { 090 if (impl == null) 091 throw new NullPointerException("impl may not be null"); 092 093 this.impl = impl; 094 this.impl.create(true); 095 setReuseAddress(true); 096 } 097 098 /* 099 * This method is only used by java.nio. 100 */ 101 102 SocketImpl getImpl() 103 { 104 return impl; 105 } 106 107 /** 108 * Constructor that simply sets the implementation. 109 * 110 * @exception IOException If an error occurs 111 * 112 * @specnote This constructor is public since JDK 1.4 113 */ 114 public ServerSocket() throws IOException 115 { 116 if (factory != null) 117 impl = factory.createSocketImpl(); 118 else 119 impl = new PlainSocketImpl(); 120 121 impl.create(true); 122 } 123 124 /** 125 * Creates a server socket and binds it to the specified port. If the 126 * port number is 0, a random free port will be chosen. The pending 127 * connection queue on this socket will be set to 50. 128 * 129 * @param port The port number to bind to 130 * 131 * @exception IOException If an error occurs 132 * @exception SecurityException If a security manager exists and its 133 * checkListen method doesn't allow the operation 134 */ 135 public ServerSocket(int port) throws IOException 136 { 137 this(port, 50); 138 } 139 140 /** 141 * Creates a server socket and binds it to the specified port. If the 142 * port number is 0, a random free port will be chosen. The pending 143 * connection queue on this socket will be set to the value passed as 144 * arg2. 145 * 146 * @param port The port number to bind to 147 * @param backlog The length of the pending connection queue 148 * 149 * @exception IOException If an error occurs 150 * @exception SecurityException If a security manager exists and its 151 * checkListen method doesn't allow the operation 152 */ 153 public ServerSocket(int port, int backlog) throws IOException 154 { 155 this(port, backlog, null); 156 } 157 158 /** 159 * Creates a server socket and binds it to the specified port. If the 160 * port number is 0, a random free port will be chosen. The pending 161 * connection queue on this socket will be set to the value passed as 162 * backlog. The third argument specifies a particular local address to 163 * bind t or null to bind to all local address. 164 * 165 * @param port The port number to bind to 166 * @param backlog The length of the pending connection queue 167 * @param bindAddr The address to bind to, or null to bind to all addresses 168 * 169 * @exception IOException If an error occurs 170 * @exception SecurityException If a security manager exists and its 171 * checkListen method doesn't allow the operation 172 * 173 * @since 1.1 174 */ 175 public ServerSocket(int port, int backlog, InetAddress bindAddr) 176 throws IOException 177 { 178 this(); 179 180 // bind/listen socket 181 bind(new InetSocketAddress(bindAddr, port), backlog); 182 } 183 184 /** 185 * Binds the server socket to a specified socket address 186 * 187 * @param endpoint The socket address to bind to 188 * 189 * @exception IOException If an error occurs 190 * @exception IllegalArgumentException If address type is not supported 191 * @exception SecurityException If a security manager exists and its 192 * checkListen method doesn't allow the operation 193 * 194 * @since 1.4 195 */ 196 public void bind(SocketAddress endpoint) throws IOException 197 { 198 bind(endpoint, 50); 199 } 200 201 /** 202 * Binds the server socket to a specified socket address 203 * 204 * @param endpoint The socket address to bind to 205 * @param backlog The length of the pending connection queue 206 * 207 * @exception IOException If an error occurs 208 * @exception IllegalArgumentException If address type is not supported 209 * @exception SecurityException If a security manager exists and its 210 * checkListen method doesn't allow the operation 211 * 212 * @since 1.4 213 */ 214 public void bind(SocketAddress endpoint, int backlog) 215 throws IOException 216 { 217 if (isClosed()) 218 throw new SocketException("ServerSocket is closed"); 219 220 if (isBound()) 221 throw new SocketException("Already bound"); 222 223 InetAddress addr; 224 int port; 225 226 if (endpoint == null) 227 { 228 addr = InetAddress.ANY_IF; 229 port = 0; 230 } 231 else if (! (endpoint instanceof InetSocketAddress)) 232 { 233 throw new IllegalArgumentException("Address type not supported"); 234 } 235 else 236 { 237 InetSocketAddress tmp = (InetSocketAddress) endpoint; 238 if (tmp.isUnresolved()) 239 throw new SocketException("Unresolved address"); 240 addr = tmp.getAddress(); 241 port = tmp.getPort(); 242 } 243 244 SecurityManager s = System.getSecurityManager(); 245 if (s != null) 246 s.checkListen(port); 247 248 try 249 { 250 impl.bind(addr, port); 251 impl.listen(backlog); 252 this.port = port; 253 local = new InetSocketAddress( 254 (InetAddress) impl.getOption(SocketOptions.SO_BINDADDR), 255 impl.getLocalPort()); 256 } 257 finally 258 { 259 try 260 { 261 if (local == null) 262 close(); 263 } 264 catch (IOException _) 265 { 266 } 267 } 268 } 269 270 /** 271 * This method returns the local address to which this socket is bound 272 * 273 * @return The socket's local address 274 */ 275 public InetAddress getInetAddress() 276 { 277 if (local == null) 278 return null; 279 280 return local.getAddress(); 281 } 282 283 /** 284 * This method returns the local port number to which this socket is bound 285 * 286 * @return The socket's port number 287 */ 288 public int getLocalPort() 289 { 290 if (local == null) 291 return -1; 292 293 return local.getPort(); 294 } 295 296 /** 297 * Returns the local socket address 298 * 299 * @return the local socket address, null if not bound 300 * 301 * @since 1.4 302 */ 303 public SocketAddress getLocalSocketAddress() 304 { 305 return local; 306 } 307 308 /** 309 * Accepts a new connection and returns a connected <code>Socket</code> 310 * instance representing that connection. This method will block until a 311 * connection is available. 312 * 313 * @return socket object for the just accepted connection 314 * 315 * @exception IOException If an error occurs 316 * @exception SecurityException If a security manager exists and its 317 * checkListen method doesn't allow the operation 318 * @exception IllegalBlockingModeException If this socket has an associated 319 * channel, and the channel is in non-blocking mode 320 * @exception SocketTimeoutException If a timeout was previously set with 321 * setSoTimeout and the timeout has been reached 322 */ 323 public Socket accept() throws IOException 324 { 325 Socket socket = new Socket(); 326 327 try 328 { 329 implAccept(socket); 330 } 331 catch (IOException e) 332 { 333 try 334 { 335 socket.close(); 336 } 337 catch (IOException e2) 338 { 339 // Ignore. 340 } 341 342 throw e; 343 } 344 catch (SecurityException e) 345 { 346 try 347 { 348 socket.close(); 349 } 350 catch (IOException e2) 351 { 352 // Ignore. 353 } 354 355 throw e; 356 } 357 358 return socket; 359 } 360 361 /** 362 * This protected method is used to help subclasses override 363 * <code>ServerSocket.accept()</code>. The passed in socket will be 364 * connected when this method returns. 365 * 366 * @param socket The socket that is used for the accepted connection 367 * 368 * @exception IOException If an error occurs 369 * @exception IllegalBlockingModeException If this socket has an associated 370 * channel, and the channel is in non-blocking mode 371 * 372 * @since 1.1 373 */ 374 protected final void implAccept(Socket socket) throws IOException 375 { 376 if (isClosed()) 377 throw new SocketException("ServerSocket is closed"); 378 379 // The Sun spec says that if we have an associated channel and 380 // it is in non-blocking mode, we throw an IllegalBlockingModeException. 381 // However, in our implementation if the channel itself initiated this 382 // operation, then we must honor it regardless of its blocking mode. 383 if (getChannel() != null && ! getChannel().isBlocking() 384 && ! ((PlainSocketImpl) getImpl()).isInChannelOperation()) 385 throw new IllegalBlockingModeException(); 386 387 impl.accept(socket.impl); 388 socket.bound = true; 389 socket.implCreated = true; 390 391 SecurityManager sm = System.getSecurityManager(); 392 if (sm != null) 393 sm.checkAccept(socket.getInetAddress().getHostAddress(), 394 socket.getPort()); 395 } 396 397 /** 398 * Closes this socket and stops listening for connections 399 * 400 * @exception IOException If an error occurs 401 */ 402 public void close() throws IOException 403 { 404 if (impl != null) 405 { 406 impl.close(); 407 impl = null; 408 } 409 } 410 411 /** 412 * Returns the unique <code>ServerSocketChannel</code> object 413 * associated with this socket, if any. 414 * 415 * <p>The socket only has a <code>ServerSocketChannel</code> if its created 416 * by <code>ServerSocketChannel.open()</code>.</p> 417 * 418 * @return the associated socket channel, null if none exists 419 * 420 * @since 1.4 421 */ 422 public ServerSocketChannel getChannel() 423 { 424 return null; 425 } 426 427 /** 428 * Returns true when the socket is bound, otherwise false 429 * 430 * @return true if socket is bound, false otherwise 431 * 432 * @since 1.4 433 */ 434 public boolean isBound() 435 { 436 return local != null; 437 } 438 439 /** 440 * Returns true if the socket is closed, otherwise false 441 * 442 * @return true if socket is closed, false otherwise 443 * 444 * @since 1.4 445 */ 446 public boolean isClosed() 447 { 448 ServerSocketChannel channel = getChannel(); 449 return impl == null || (channel != null && ! channel.isOpen()); 450 } 451 452 /** 453 * Sets the value of SO_TIMEOUT. A value of 0 implies that SO_TIMEOUT is 454 * disabled (ie, operations never time out). This is the number of 455 * milliseconds a socket operation can block before an 456 * InterruptedIOException is thrown. 457 * 458 * @param timeout The new SO_TIMEOUT value 459 * 460 * @exception SocketException If an error occurs 461 * 462 * @since 1.1 463 */ 464 public void setSoTimeout(int timeout) throws SocketException 465 { 466 if (isClosed()) 467 throw new SocketException("ServerSocket is closed"); 468 469 if (timeout < 0) 470 throw new IllegalArgumentException("SO_TIMEOUT value must be >= 0"); 471 472 impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout)); 473 } 474 475 /** 476 * Retrieves the current value of the SO_TIMEOUT setting. A value of 0 477 * implies that SO_TIMEOUT is disabled (ie, operations never time out). 478 * This is the number of milliseconds a socket operation can block before 479 * an InterruptedIOException is thrown. 480 * 481 * @return The value of SO_TIMEOUT 482 * 483 * @exception IOException If an error occurs 484 * 485 * @since 1.1 486 */ 487 public int getSoTimeout() throws IOException 488 { 489 if (isClosed()) 490 throw new SocketException("ServerSocket is closed"); 491 492 Object timeout = impl.getOption(SocketOptions.SO_TIMEOUT); 493 494 if (! (timeout instanceof Integer)) 495 throw new IOException("Internal Error"); 496 497 return ((Integer) timeout).intValue(); 498 } 499 500 /** 501 * Enables/Disables the SO_REUSEADDR option 502 * 503 * @param on true if SO_REUSEADDR should be enabled, false otherwise 504 * 505 * @exception SocketException If an error occurs 506 * 507 * @since 1.4 508 */ 509 public void setReuseAddress(boolean on) throws SocketException 510 { 511 if (isClosed()) 512 throw new SocketException("ServerSocket is closed"); 513 514 impl.setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on)); 515 } 516 517 /** 518 * Checks if the SO_REUSEADDR option is enabled 519 * 520 * @return true if SO_REUSEADDR is set, false otherwise 521 * 522 * @exception SocketException If an error occurs 523 * 524 * @since 1.4 525 */ 526 public boolean getReuseAddress() throws SocketException 527 { 528 if (isClosed()) 529 throw new SocketException("ServerSocket is closed"); 530 531 Object reuseaddr = impl.getOption(SocketOptions.SO_REUSEADDR); 532 533 if (! (reuseaddr instanceof Boolean)) 534 throw new SocketException("Internal Error"); 535 536 return ((Boolean) reuseaddr).booleanValue(); 537 } 538 539 /** 540 * This method sets the value for the system level socket option 541 * SO_RCVBUF to the specified value. Note that valid values for this 542 * option are specific to a given operating system. 543 * 544 * @param size The new receive buffer size. 545 * 546 * @exception SocketException If an error occurs or Socket is not connected 547 * @exception IllegalArgumentException If size is 0 or negative 548 * 549 * @since 1.4 550 */ 551 public void setReceiveBufferSize(int size) throws SocketException 552 { 553 if (isClosed()) 554 throw new SocketException("ServerSocket is closed"); 555 556 if (size <= 0) 557 throw new IllegalArgumentException("SO_RCVBUF value must be > 0"); 558 559 impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size)); 560 } 561 562 /** 563 * This method returns the value of the system level socket option 564 * SO_RCVBUF, which is used by the operating system to tune buffer 565 * sizes for data transfers. 566 * 567 * @return The receive buffer size. 568 * 569 * @exception SocketException If an error occurs or Socket is not connected 570 * 571 * @since 1.4 572 */ 573 public int getReceiveBufferSize() throws SocketException 574 { 575 if (isClosed()) 576 throw new SocketException("ServerSocket is closed"); 577 578 Object buf = impl.getOption(SocketOptions.SO_RCVBUF); 579 580 if (! (buf instanceof Integer)) 581 throw new SocketException("Internal Error: Unexpected type"); 582 583 return ((Integer) buf).intValue(); 584 } 585 586 /** 587 * Returns the value of this socket as a <code>String</code>. 588 * 589 * @return This socket represented as a <code>String</code>. 590 */ 591 public String toString() 592 { 593 if (! isBound()) 594 return "ServerSocket[unbound]"; 595 596 return ("ServerSocket[addr=" + getInetAddress() + ",port=" 597 + port + ",localport=" + getLocalPort() + "]"); 598 } 599 600 /** 601 * Sets the <code>SocketImplFactory</code> for all 602 * <code>ServerSocket</code>'s. This may only be done 603 * once per virtual machine. Subsequent attempts will generate an 604 * exception. Note that a <code>SecurityManager</code> check is made prior 605 * to setting the factory. If insufficient privileges exist to set the 606 * factory, an exception will be thrown 607 * 608 * @param fac the factory to set 609 * 610 * @exception SecurityException If this operation is not allowed by the 611 * <code>SecurityManager</code>. 612 * @exception SocketException If the factory object is already defined 613 * @exception IOException If any other error occurs 614 */ 615 public static synchronized void setSocketFactory(SocketImplFactory fac) 616 throws IOException 617 { 618 if (factory != null) 619 throw new SocketException("SocketFactory already defined"); 620 621 SecurityManager sm = System.getSecurityManager(); 622 if (sm != null) 623 sm.checkSetFactory(); 624 625 factory = fac; 626 } 627}