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