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