DatagramSocket.java revision f5597e626ecf7949d249dea08c1a2964d890ec11
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package java.net; 19 20import java.io.IOException; 21import java.nio.channels.DatagramChannel; 22 23import org.apache.harmony.luni.net.PlainDatagramSocketImpl; 24import org.apache.harmony.luni.platform.Platform; 25import org.apache.harmony.luni.util.Msg; 26 27/** 28 * This class implements a UDP socket for sending and receiving {@code 29 * DatagramPacket}. A {@code DatagramSocket} object can be used for both 30 * endpoints of a connection for a packet delivery service. 31 * 32 * @see DatagramPacket 33 * @see DatagramSocketImplFactory 34 */ 35public class DatagramSocket { 36 37 DatagramSocketImpl impl; 38 39 InetAddress address; 40 41 int port = -1; 42 43 static DatagramSocketImplFactory factory; 44 45 boolean isBound = false; 46 47 private boolean isConnected = false; 48 49 private boolean isClosed = false; 50 51 private static class Lock { 52 } 53 54 static { 55 Platform.getNetworkSystem().oneTimeInitialization(true); 56 } 57 58 private Object lock = new Lock(); 59 60 /** 61 * Constructs a UDP datagram socket which is bound to any available port on 62 * the localhost. 63 * 64 * @throws SocketException 65 * if an error occurs while creating or binding the socket. 66 */ 67 public DatagramSocket() throws SocketException { 68 this(0); 69 } 70 71 /** 72 * Constructs a UDP datagram socket which is bound to the specific port 73 * {@code aPort} on the localhost. Valid values for {@code aPort} are 74 * between 0 and 65535 inclusive. 75 * 76 * @param aPort 77 * the port to bind on the localhost. 78 * @throws SocketException 79 * if an error occurs while creating or binding the socket. 80 */ 81 public DatagramSocket(int aPort) throws SocketException { 82 super(); 83 checkListen(aPort); 84 createSocket(aPort, InetAddress.ANY); 85 } 86 87 /** 88 * Constructs a UDP datagram socket which is bound to the specific local 89 * address {@code addr} on port {@code aPort}. Valid values for {@code 90 * aPort} are between 0 and 65535 inclusive. 91 * 92 * @param aPort 93 * the port to bind on the localhost. 94 * @param addr 95 * the address to bind on the localhost. 96 * @throws SocketException 97 * if an error occurs while creating or binding the socket. 98 */ 99 public DatagramSocket(int aPort, InetAddress addr) throws SocketException { 100 super(); 101 checkListen(aPort); 102 createSocket(aPort, null == addr ? InetAddress.ANY : addr); 103 } 104 105 /** 106 * Sends prior to attempting to bind the socket, checks whether the port is 107 * within the valid port range and verifies with the security manager that 108 * the port may be bound by the current context. 109 * 110 * @param aPort 111 * the port on the localhost that is to be bound. 112 */ 113 void checkListen(int aPort) { 114 if (aPort < 0 || aPort > 65535) { 115 throw new IllegalArgumentException(Msg.getString("K0325", aPort)); //$NON-NLS-1$ 116 } 117 SecurityManager security = System.getSecurityManager(); 118 if (security != null) { 119 security.checkListen(aPort); 120 } 121 } 122 123 /** 124 * Closes this UDP datagram socket and all possibly associated channels. 125 */ 126 // In the documentation jdk1.1.7a/guide/net/miscNet.html, this method is 127 // noted as not being synchronized. 128 public void close() { 129 isClosed = true; 130 impl.close(); 131 } 132 133 /** 134 * Connects this UDP datagram socket to the specific target host with the 135 * address {@code anAdress} on port {@code aPort}. The host and port are 136 * validated, thereafter the only validation on {@code send()} and {@code 137 * receive()} is to check whether the packet address/port matches the 138 * connected target. 139 * 140 * @param anAddress 141 * the target address of this socket. 142 * @param aPort 143 * the target port of this socket. 144 */ 145 public void connect(InetAddress anAddress, int aPort) { 146 if (anAddress == null || aPort < 0 || aPort > 65535) { 147 throw new IllegalArgumentException(Msg.getString("K0032")); //$NON-NLS-1$ 148 } 149 150 synchronized (lock) { 151 if (isClosed()) { 152 return; 153 } 154 try { 155 checkClosedAndBind(true); 156 } catch (SocketException e) { 157 // Ignored 158 } 159 160 SecurityManager security = System.getSecurityManager(); 161 if (security != null) { 162 if (anAddress.isMulticastAddress()) { 163 security.checkMulticast(anAddress); 164 } else { 165 security.checkConnect(anAddress.getHostName(), aPort); 166 } 167 } 168 169 try { 170 impl.connect(anAddress, aPort); 171 } catch (SocketException e) { 172 // not connected at the native level just do what we did before 173 } 174 address = anAddress; 175 port = aPort; 176 isConnected = true; 177 } 178 } 179 180 /** 181 * Disconnects this UDP datagram socket from the remote host. This method 182 * called on an unconnected socket does nothing. 183 */ 184 public void disconnect() { 185 if (isClosed() || !isConnected()) { 186 return; 187 } 188 impl.disconnect(); 189 address = null; 190 port = -1; 191 isConnected = false; 192 } 193 194 synchronized void createSocket(int aPort, InetAddress addr) 195 throws SocketException { 196 impl = factory != null ? factory.createDatagramSocketImpl() 197 : new PlainDatagramSocketImpl(); 198 impl.create(); 199 try { 200 impl.bind(aPort, addr); 201 isBound = true; 202 } catch (SocketException e) { 203 close(); 204 throw e; 205 } 206 } 207 208 /** 209 * Gets the {@code InetAddress} instance representing the remote address to 210 * which this UDP datagram socket is connected. 211 * 212 * @return the remote address this socket is connected to or {@code null} if 213 * this socket is not connected. 214 */ 215 public InetAddress getInetAddress() { 216 return address; 217 } 218 219 /** 220 * Gets the {@code InetAddress} instance representing the bound local 221 * address of this UDP datagram socket. 222 * 223 * @return the local address to which this socket is bound to or {@code 224 * null} if this socket is closed. 225 */ 226 public InetAddress getLocalAddress() { 227 if (isClosed()) { 228 return null; 229 } 230 if (!isBound()) { 231 return InetAddress.ANY; 232 } 233 InetAddress anAddr = impl.getLocalAddress(); 234 try { 235 SecurityManager security = System.getSecurityManager(); 236 if (security != null) { 237 security.checkConnect(anAddr.getHostName(), -1); 238 } 239 } catch (SecurityException e) { 240 return InetAddress.ANY; 241 } 242 return anAddr; 243 } 244 245 /** 246 * Gets the local port which this socket is bound to. 247 * 248 * @return the local port of this socket or {@code -1} if this socket is 249 * closed and {@code 0} if it is unbound. 250 */ 251 public int getLocalPort() { 252 if (isClosed()) { 253 return -1; 254 } 255 if (!isBound()) { 256 return 0; 257 } 258 return impl.getLocalPort(); 259 } 260 261 /** 262 * Gets the remote port which this socket is connected to. 263 * 264 * @return the remote port of this socket. The return value {@code -1} 265 * indicates that this socket is not connected. 266 */ 267 public int getPort() { 268 return port; 269 } 270 271 /** 272 * Indicates whether this socket is multicast or not. 273 * 274 * @return the return value is always {@code false}. 275 */ 276 boolean isMulticastSocket() { 277 return false; 278 } 279 280 /** 281 * Gets the socket receive buffer size. ( {@code SocketOptions.SO_RCVBUF} ) 282 * 283 * @return the input buffer size. 284 * @throws SocketException 285 * if an error occurs while getting the option value. 286 */ 287 public synchronized int getReceiveBufferSize() throws SocketException { 288 checkClosedAndBind(false); 289 return ((Integer) impl.getOption(SocketOptions.SO_RCVBUF)).intValue(); 290 } 291 292 /** 293 * Gets the socket send buffer size. ( {@code SocketOptions.SO_SNDBUF} ) 294 * 295 * @return the output buffer size. 296 * @throws SocketException 297 * if an error occurs while getting the option value. 298 */ 299 public synchronized int getSendBufferSize() throws SocketException { 300 checkClosedAndBind(false); 301 return ((Integer) impl.getOption(SocketOptions.SO_SNDBUF)).intValue(); 302 } 303 304 /** 305 * Gets the socket receive timeout in milliseconds. The return value {@code 306 * 0} implies the timeout is disabled/infinitive. ( {@code 307 * SocketOptions.SO_TIMEOUT} ) 308 * 309 * @return the socket receive timeout. 310 * @throws SocketException 311 * if an error occurs while getting the option value. 312 */ 313 public synchronized int getSoTimeout() throws SocketException { 314 checkClosedAndBind(false); 315 return ((Integer) impl.getOption(SocketOptions.SO_TIMEOUT)).intValue(); 316 } 317 318 /** 319 * Receives a packet from this socket and stores it in the argument {@code 320 * pack}. All fields of {@code pack} must be set according to the data 321 * received. If the received data is longer than the packet buffer size it 322 * is truncated. This method blocks until a packet is received or a timeout 323 * has expired. If a security manager exists, its {@code checkAccept} method 324 * determines whether or not a packet is discarded. Any packets from 325 * unacceptable origins are silently discarded. 326 * 327 * @param pack 328 * the {@code DatagramPacket} to store the received data. 329 * @throws IOException 330 * if an error occurs while receiving the packet. 331 */ 332 public synchronized void receive(DatagramPacket pack) throws IOException { 333 checkClosedAndBind(true); 334 335 InetAddress senderAddr; 336 int senderPort; 337 DatagramPacket tempPack = new DatagramPacket(new byte[1], 1); 338 339 // means that we have received the packet into the temporary buffer 340 boolean copy = false; 341 342 SecurityManager security = System.getSecurityManager(); 343 344 if (address != null || security != null) { 345 // The socket is connected or we need to check security permissions 346 347 // Check pack before peeking 348 if (pack == null) { 349 throw new NullPointerException(); 350 } 351 352 // iterate over incoming packets 353 while (true) { 354 copy = false; 355 356 // let's get sender's address and port 357 try { 358 senderPort = impl.peekData(tempPack); 359 senderAddr = tempPack.getAddress(); 360 } catch (SocketException e) { 361 if (e.getMessage().equals( 362 "The socket does not support the operation")) { //$NON-NLS-1$ 363 // receive packet to temporary buffer 364 tempPack = new DatagramPacket(new byte[pack.capacity], 365 pack.capacity); 366 impl.receive(tempPack); 367 // tempPack's length field is now updated, capacity is unchanged 368 // let's extract address & port 369 senderAddr = tempPack.getAddress(); 370 senderPort = tempPack.getPort(); 371 copy = true; 372 } else { 373 throw e; 374 } 375 } 376 377 if (address == null) { 378 // if we are not connected let's check if we are allowed to 379 // receive packets from sender's address and port 380 try { 381 security.checkAccept(senderAddr.getHostName(), 382 senderPort); 383 // address & port are valid 384 break; 385 } catch (SecurityException e) { 386 if (!copy) { 387 // drop this packet and continue 388 impl.receive(tempPack); 389 } 390 } 391 } else if (port == senderPort && address.equals(senderAddr)) { 392 // we are connected and the packet came 393 // from the address & port we are connected to 394 break; 395 } else if (!copy) { 396 // drop packet and continue 397 impl.receive(tempPack); 398 } 399 } 400 } 401 402 if (copy) { 403 System.arraycopy(tempPack.getData(), 0, pack.getData(), pack 404 .getOffset(), tempPack.getLength()); 405 // we shouldn't update the pack's capacity field in order to be 406 // compatible with RI 407 pack.length = tempPack.length; 408 pack.setAddress(tempPack.getAddress()); 409 pack.setPort(tempPack.getPort()); 410 } else { 411 pack.setLength(pack.capacity); 412 impl.receive(pack); 413 // pack's length field is now updated by native code call; 414 // pack's capacity field is unchanged 415 } 416 } 417 418 /** 419 * Sends a packet over this socket. The packet must satisfy the security 420 * policy before it may be sent. If a security manager is installed, this 421 * method checks whether it is allowed to send this packet to the specified 422 * address. 423 * 424 * @param pack 425 * the {@code DatagramPacket} which has to be sent. 426 * @throws IOException 427 * if an error occurs while sending the packet. 428 */ 429 public void send(DatagramPacket pack) throws IOException { 430 checkClosedAndBind(true); 431 432 InetAddress packAddr = pack.getAddress(); 433 if (address != null) { // The socket is connected 434 if (packAddr != null) { 435 if (!address.equals(packAddr) || port != pack.getPort()) { 436 throw new IllegalArgumentException(Msg.getString("K0034")); //$NON-NLS-1$ 437 } 438 } else { 439 pack.setAddress(address); 440 pack.setPort(port); 441 } 442 } else { 443 // not connected so the target address is not allowed to be null 444 if (packAddr == null) { 445 if (pack.port == -1) { 446 // KA019 Destination address is null 447 throw new NullPointerException(Msg.getString("KA019")); //$NON-NLS-1$ 448 } 449 return; 450 } 451 SecurityManager security = System.getSecurityManager(); 452 if (security != null) { 453 if (packAddr.isMulticastAddress()) { 454 security.checkMulticast(packAddr); 455 } else { 456 security.checkConnect(packAddr.getHostName(), pack 457 .getPort()); 458 } 459 } 460 } 461 impl.send(pack); 462 } 463 464 /** 465 * Sets the socket send buffer size. This buffer size determines which the 466 * maximum packet size is that can be sent over this socket. It depends on 467 * the network implementation what will happen if the packet is bigger than 468 * the buffer size. ( {@code SocketOptions.SO_SNDBUF} ) 469 * 470 * @param size 471 * the buffer size in bytes. The size must be at least one byte. 472 * @throws SocketException 473 * if an error occurs while setting the option. 474 */ 475 public synchronized void setSendBufferSize(int size) throws SocketException { 476 if (size < 1) { 477 throw new IllegalArgumentException(Msg.getString("K0035")); //$NON-NLS-1$ 478 } 479 checkClosedAndBind(false); 480 impl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size)); 481 } 482 483 /** 484 * Sets the socket receive buffer size. This buffer size determines which 485 * the maximum packet size is that can be received over this socket. It 486 * depends on the network implementation what will happen if the packet is 487 * bigger than the buffer size. ( {@code SocketOptions.SO_RCVBUF} ) 488 * 489 * @param size 490 * the buffer size in bytes. The size must be at least one byte. 491 * @throws SocketException 492 * if an error occurs while setting the option. 493 */ 494 public synchronized void setReceiveBufferSize(int size) 495 throws SocketException { 496 if (size < 1) { 497 throw new IllegalArgumentException(Msg.getString("K0035")); //$NON-NLS-1$ 498 } 499 checkClosedAndBind(false); 500 impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size)); 501 } 502 503 /** 504 * Sets the timeout period in milliseconds for the {@code receive()} method. 505 * This receive timeout defines the period the socket will block waiting to 506 * receive data before throwing an {@code InterruptedIOException}. The value 507 * {@code 0} (default) is used to set an infinite timeout. To have effect 508 * this option must be set before the blocking method was called. ( {@code 509 * SocketOptions.SO_TIMEOUT} ) 510 * 511 * @param timeout 512 * the timeout period in milliseconds or {@code 0} for infinite. 513 * @throws SocketException 514 * if an error occurs while setting the option. 515 */ 516 public synchronized void setSoTimeout(int timeout) throws SocketException { 517 if (timeout < 0) { 518 throw new IllegalArgumentException(Msg.getString("K0036")); //$NON-NLS-1$ 519 } 520 checkClosedAndBind(false); 521 impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout)); 522 } 523 524 /** 525 * Sets the socket implementation factory. This may only be invoked once 526 * over the lifetime of the application. This factory is used to create 527 * a new datagram socket implementation. If a security manager is set its 528 * method {@code checkSetFactory()} is called to check if the operation is 529 * allowed. A {@code SecurityException} is thrown if the operation is not 530 * allowed. 531 * 532 * @param fac 533 * the socket factory to use. 534 * @throws IOException 535 * if the factory has already been set. 536 * @see DatagramSocketImplFactory 537 */ 538 public static synchronized void setDatagramSocketImplFactory( 539 DatagramSocketImplFactory fac) throws IOException { 540 SecurityManager security = System.getSecurityManager(); 541 if (security != null) { 542 security.checkSetFactory(); 543 } 544 if (factory != null) { 545 throw new SocketException(Msg.getString("K0044")); //$NON-NLS-1$ 546 } 547 factory = fac; 548 } 549 550 /** 551 * Constructs a new {@code DatagramSocket} using the specific datagram 552 * socket implementation {@code socketImpl}. The created {@code 553 * DatagramSocket} will not be bound. 554 * 555 * @param socketImpl 556 * the DatagramSocketImpl to use. 557 */ 558 protected DatagramSocket(DatagramSocketImpl socketImpl) { 559 if (socketImpl == null) { 560 throw new NullPointerException(); 561 } 562 impl = socketImpl; 563 } 564 565 /** 566 * Constructs a new {@code DatagramSocket} bound to the host/port specified 567 * by the {@code SocketAddress} {@code localAddr} or an unbound {@code 568 * DatagramSocket} if the {@code SocketAddress} is {@code null}. 569 * 570 * @param localAddr 571 * the local machine address and port to bind to. 572 * @throws IllegalArgumentException 573 * if the SocketAddress is not supported 574 * @throws SocketException 575 * if a problem occurs creating or binding the socket. 576 */ 577 public DatagramSocket(SocketAddress localAddr) throws SocketException { 578 if (localAddr != null) { 579 if (!(localAddr instanceof InetSocketAddress)) { 580 throw new IllegalArgumentException(Msg.getString( 581 "K0316", localAddr.getClass())); //$NON-NLS-1$ 582 } 583 checkListen(((InetSocketAddress) localAddr).getPort()); 584 } 585 impl = factory != null ? factory.createDatagramSocketImpl() 586 : new PlainDatagramSocketImpl(); 587 impl.create(); 588 if (localAddr != null) { 589 try { 590 bind(localAddr); 591 } catch (SocketException e) { 592 close(); 593 throw e; 594 } 595 } 596 // SocketOptions.SO_BROADCAST is set by default for DatagramSocket 597 setBroadcast(true); 598 } 599 600 void checkClosedAndBind(boolean bind) throws SocketException { 601 if (isClosed()) { 602 throw new SocketException(Msg.getString("K003d")); //$NON-NLS-1$ 603 } 604 if (bind && !isBound()) { 605 checkListen(0); 606 impl.bind(0, InetAddress.ANY); 607 isBound = true; 608 } 609 } 610 611 /** 612 * Binds this socket to the local address and port specified by {@code 613 * localAddr}. If this value is {@code null} any free port on a valid local 614 * address is used. 615 * 616 * @param localAddr 617 * the local machine address and port to bind on. 618 * @throws IllegalArgumentException 619 * if the SocketAddress is not supported 620 * @throws SocketException 621 * if the socket is already bound or a problem occurs during 622 * binding. 623 */ 624 public void bind(SocketAddress localAddr) throws SocketException { 625 checkClosedAndBind(false); 626 int localPort = 0; 627 InetAddress addr = InetAddress.ANY; 628 if (localAddr != null) { 629 if (!(localAddr instanceof InetSocketAddress)) { 630 throw new IllegalArgumentException(Msg.getString( 631 "K0316", localAddr.getClass())); //$NON-NLS-1$ 632 } 633 InetSocketAddress inetAddr = (InetSocketAddress) localAddr; 634 addr = inetAddr.getAddress(); 635 if (addr == null) { 636 throw new SocketException(Msg.getString( 637 "K0317", inetAddr.getHostName())); //$NON-NLS-1$ 638 } 639 localPort = inetAddr.getPort(); 640 checkListen(localPort); 641 } 642 impl.bind(localPort, addr); 643 isBound = true; 644 } 645 646 /** 647 * Connects this datagram socket to the remote host and port specified by 648 * {@code remoteAddr}. The host and port are validated, thereafter the only 649 * validation on {@code send()} and {@code receive()} is that the packet 650 * address/port matches the connected target. 651 * 652 * @param remoteAddr 653 * the address and port of the target host. 654 * @throws SocketException 655 * if an error occurs during connecting. 656 */ 657 public void connect(SocketAddress remoteAddr) throws SocketException { 658 if (remoteAddr == null) { 659 throw new IllegalArgumentException(Msg.getString("K0318")); //$NON-NLS-1$ 660 } 661 662 if (!(remoteAddr instanceof InetSocketAddress)) { 663 throw new IllegalArgumentException(Msg.getString( 664 "K0316", remoteAddr.getClass())); //$NON-NLS-1$ 665 } 666 667 InetSocketAddress inetAddr = (InetSocketAddress) remoteAddr; 668 if (inetAddr.getAddress() == null) { 669 throw new SocketException(Msg.getString( 670 "K0317", inetAddr.getHostName())); //$NON-NLS-1$ 671 } 672 673 synchronized (lock) { 674 // make sure the socket is open 675 checkClosedAndBind(true); 676 677 SecurityManager security = System.getSecurityManager(); 678 if (security != null) { 679 if (inetAddr.getAddress().isMulticastAddress()) { 680 security.checkMulticast(inetAddr.getAddress()); 681 } else { 682 security.checkConnect(inetAddr.getAddress().getHostName(), 683 inetAddr.getPort()); 684 } 685 } 686 687 // now try to do the connection at the native level. To be 688 // compatible for the case when the address is inaddr_any we just 689 // eat the exception an act as if we are connected at the java level 690 try { 691 impl.connect(inetAddr.getAddress(), inetAddr.getPort()); 692 } catch (Exception e) { 693 // not connected at the native level just do what we did before 694 } 695 696 // if we get here then we connected ok 697 address = inetAddr.getAddress(); 698 port = inetAddr.getPort(); 699 isConnected = true; 700 } 701 } 702 703 /** 704 * Determines whether the socket is bound to an address or not. 705 * 706 * @return {@code true} if the socket is bound, {@code false} otherwise. 707 */ 708 public boolean isBound() { 709 return isBound; 710 } 711 712 /** 713 * Determines whether the socket is connected to a target host. 714 * 715 * @return {@code true} if the socket is connected, {@code false} otherwise. 716 */ 717 public boolean isConnected() { 718 return isConnected; 719 } 720 721 /** 722 * Gets the address and port of the connected remote host. If this socket is 723 * not connected yet, {@code null} is returned. 724 * 725 * @return the remote socket address. 726 */ 727 public SocketAddress getRemoteSocketAddress() { 728 if (!isConnected()) { 729 return null; 730 } 731 return new InetSocketAddress(getInetAddress(), getPort()); 732 } 733 734 /** 735 * Gets the bound local address and port of this socket. If the socket is 736 * unbound, {@code null} is returned. 737 * 738 * @return the local socket address. 739 */ 740 public SocketAddress getLocalSocketAddress() { 741 if (!isBound()) { 742 return null; 743 } 744 return new InetSocketAddress(getLocalAddress(), getLocalPort()); 745 } 746 747 /** 748 * Sets the socket option {@code SocketOptions.SO_REUSEADDR}. This option 749 * has to be enabled if more than one UDP socket wants to be bound to the 750 * same address. That could be needed for receiving multicast packets. 751 * <p> 752 * There is an undefined behavior if this option is set after the socket is 753 * already bound. 754 * 755 * @param reuse 756 * the socket option value to enable or disable this option. 757 * @throws SocketException 758 * if the socket is closed or the option could not be set. 759 */ 760 public void setReuseAddress(boolean reuse) throws SocketException { 761 checkClosedAndBind(false); 762 impl.setOption(SocketOptions.SO_REUSEADDR, reuse ? Boolean.TRUE 763 : Boolean.FALSE); 764 } 765 766 /** 767 * Gets the state of the socket option {@code SocketOptions.SO_REUSEADDR}. 768 * 769 * @return {@code true} if the option is enabled, {@code false} otherwise. 770 * @throws SocketException 771 * if the socket is closed or the option is invalid. 772 */ 773 public boolean getReuseAddress() throws SocketException { 774 checkClosedAndBind(false); 775 return ((Boolean) impl.getOption(SocketOptions.SO_REUSEADDR)) 776 .booleanValue(); 777 } 778 779 /** 780 * Sets the socket option {@code SocketOptions.SO_BROADCAST}. This option 781 * must be enabled to send broadcast messages. 782 * 783 * @param broadcast 784 * the socket option value to enable or disable this option. 785 * @throws SocketException 786 * if the socket is closed or the option could not be set. 787 */ 788 public void setBroadcast(boolean broadcast) throws SocketException { 789 checkClosedAndBind(false); 790 impl.setOption(SocketOptions.SO_BROADCAST, broadcast ? Boolean.TRUE 791 : Boolean.FALSE); 792 } 793 794 /** 795 * Gets the state of the socket option {@code SocketOptions.SO_BROADCAST}. 796 * 797 * @return {@code true} if the option is enabled, {@code false} otherwise. 798 * @throws SocketException 799 * if the socket is closed or the option is invalid. 800 */ 801 public boolean getBroadcast() throws SocketException { 802 checkClosedAndBind(false); 803 return ((Boolean) impl.getOption(SocketOptions.SO_BROADCAST)) 804 .booleanValue(); 805 } 806 807 /** 808 * Sets the socket option {@code SocketOptions.IP_TOS}. This option defines 809 * the value of the type-of-service field of the IP-header for every packet 810 * sent by this socket. The value could be ignored by the underlying network 811 * implementation. 812 * <p> 813 * Values between {@code 0} and {@code 255} inclusive are valid for this 814 * option. 815 * 816 * @param value 817 * the socket option value to be set as type-of-service. 818 * @throws SocketException 819 * if the socket is closed or the option could not be set. 820 */ 821 public void setTrafficClass(int value) throws SocketException { 822 checkClosedAndBind(false); 823 if (value < 0 || value > 255) { 824 throw new IllegalArgumentException(); 825 } 826 impl.setOption(SocketOptions.IP_TOS, Integer.valueOf(value)); 827 } 828 829 /** 830 * Gets the value of the type-of-service socket option {@code 831 * SocketOptions.IP_TOS}. 832 * 833 * @return the type-of-service socket option value. 834 * @throws SocketException 835 * if the socket is closed or the option is invalid. 836 */ 837 public int getTrafficClass() throws SocketException { 838 checkClosedAndBind(false); 839 return ((Number) impl.getOption(SocketOptions.IP_TOS)).intValue(); 840 } 841 842 /** 843 * Gets the state of this socket. 844 * 845 * @return {@code true} if the socket is closed, {@code false} otherwise. 846 */ 847 public boolean isClosed() { 848 return isClosed; 849 } 850 851 /** 852 * Gets the related DatagramChannel of this socket. This implementation 853 * returns always {@code null}. 854 * 855 * @return the related DatagramChannel or {@code null} if this socket was 856 * not created by a {@code DatagramChannel} object. 857 */ 858 public DatagramChannel getChannel() { 859 return null; 860 } 861} 862