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