DatagramSocket.java revision 0d93c38cc3c7a5001aece8a18cafc6d1fc7551f3
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, null == addr ? 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 if (pack.getPort() == -1) { 433 throw new NullPointerException("Destination address is null"); 434 } 435 return; 436 } 437 SecurityManager security = System.getSecurityManager(); 438 if (security != null) { 439 if (packAddr.isMulticastAddress()) { 440 security.checkMulticast(packAddr); 441 } else { 442 security.checkConnect(packAddr.getHostName(), pack 443 .getPort()); 444 } 445 } 446 } 447 impl.send(pack); 448 } 449 450 /** 451 * Sets the socket send buffer size. This buffer size determines which the 452 * maximum packet size is that can be sent over this socket. It depends on 453 * the network implementation what will happen if the packet is bigger than 454 * the buffer size. ( {@code SocketOptions.SO_SNDBUF} ) 455 * 456 * @param size 457 * the buffer size in bytes. The size must be at least one byte. 458 * @throws SocketException 459 * if an error occurs while setting the option. 460 */ 461 public synchronized void setSendBufferSize(int size) throws SocketException { 462 if (size < 1) { 463 throw new IllegalArgumentException("size < 1"); 464 } 465 checkClosedAndBind(false); 466 impl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size)); 467 } 468 469 /** 470 * Sets the socket receive buffer size. This buffer size determines which 471 * the maximum packet size is that can be received over this socket. It 472 * depends on the network implementation what will happen if the packet is 473 * bigger than the buffer size. ( {@code SocketOptions.SO_RCVBUF} ) 474 * 475 * @param size 476 * the buffer size in bytes. The size must be at least one byte. 477 * @throws SocketException 478 * if an error occurs while setting the option. 479 */ 480 public synchronized void setReceiveBufferSize(int size) throws SocketException { 481 if (size < 1) { 482 throw new IllegalArgumentException("size < 1"); 483 } 484 checkClosedAndBind(false); 485 impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size)); 486 } 487 488 /** 489 * Sets the {@link SocketOptions#SO_TIMEOUT read timeout} in milliseconds for this socket. 490 * This receive timeout defines the period the socket will block waiting to 491 * receive data before throwing an {@code InterruptedIOException}. The value 492 * {@code 0} (default) is used to set an infinite timeout. To have effect 493 * this option must be set before the blocking method was called. 494 * 495 * @param timeout the timeout in milliseconds or 0 for no timeout. 496 * @throws SocketException 497 * if an error occurs while setting the option. 498 */ 499 public synchronized void setSoTimeout(int timeout) throws SocketException { 500 if (timeout < 0) { 501 throw new IllegalArgumentException("timeout < 0"); 502 } 503 checkClosedAndBind(false); 504 impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout)); 505 } 506 507 /** 508 * Sets the socket implementation factory. This may only be invoked once 509 * over the lifetime of the application. This factory is used to create 510 * a new datagram socket implementation. If a security manager is set its 511 * method {@code checkSetFactory()} is called to check if the operation is 512 * allowed. A {@code SecurityException} is thrown if the operation is not 513 * allowed. 514 * 515 * @param fac 516 * the socket factory to use. 517 * @throws IOException 518 * if the factory has already been set. 519 * @see DatagramSocketImplFactory 520 */ 521 public static synchronized void setDatagramSocketImplFactory( 522 DatagramSocketImplFactory fac) throws IOException { 523 SecurityManager security = System.getSecurityManager(); 524 if (security != null) { 525 security.checkSetFactory(); 526 } 527 if (factory != null) { 528 throw new SocketException("Factory already set"); 529 } 530 factory = fac; 531 } 532 533 /** 534 * Constructs a new {@code DatagramSocket} using the specific datagram 535 * socket implementation {@code socketImpl}. The created {@code 536 * DatagramSocket} will not be bound. 537 * 538 * @param socketImpl 539 * the DatagramSocketImpl to use. 540 */ 541 protected DatagramSocket(DatagramSocketImpl socketImpl) { 542 if (socketImpl == null) { 543 throw new NullPointerException(); 544 } 545 impl = socketImpl; 546 } 547 548 /** 549 * Constructs a new {@code DatagramSocket} bound to the host/port specified 550 * by the {@code SocketAddress} {@code localAddr} or an unbound {@code 551 * DatagramSocket} if the {@code SocketAddress} is {@code null}. 552 * 553 * @param localAddr 554 * the local machine address and port to bind to. 555 * @throws IllegalArgumentException 556 * if the SocketAddress is not supported 557 * @throws SocketException 558 * if a problem occurs creating or binding the socket. 559 */ 560 public DatagramSocket(SocketAddress localAddr) throws SocketException { 561 if (localAddr != null) { 562 if (!(localAddr instanceof InetSocketAddress)) { 563 throw new IllegalArgumentException("Local address not an InetSocketAddress: " + 564 localAddr.getClass()); 565 } 566 checkListen(((InetSocketAddress) localAddr).getPort()); 567 } 568 impl = factory != null ? factory.createDatagramSocketImpl() 569 : new PlainDatagramSocketImpl(); 570 impl.create(); 571 if (localAddr != null) { 572 try { 573 bind(localAddr); 574 } catch (SocketException e) { 575 close(); 576 throw e; 577 } 578 } 579 // SocketOptions.SO_BROADCAST is set by default for DatagramSocket 580 setBroadcast(true); 581 } 582 583 void checkClosedAndBind(boolean bind) throws SocketException { 584 if (isClosed()) { 585 throw new SocketException("Socket is closed"); 586 } 587 if (bind && !isBound()) { 588 checkListen(0); 589 impl.bind(0, Inet4Address.ANY); 590 isBound = true; 591 } 592 } 593 594 /** 595 * Binds this socket to the local address and port specified by {@code 596 * localAddr}. If this value is {@code null} any free port on a valid local 597 * address is used. 598 * 599 * @param localAddr 600 * the local machine address and port to bind on. 601 * @throws IllegalArgumentException 602 * if the SocketAddress is not supported 603 * @throws SocketException 604 * if the socket is already bound or a problem occurs during 605 * binding. 606 */ 607 public void bind(SocketAddress localAddr) throws SocketException { 608 checkClosedAndBind(false); 609 int localPort = 0; 610 InetAddress addr = Inet4Address.ANY; 611 if (localAddr != null) { 612 if (!(localAddr instanceof InetSocketAddress)) { 613 throw new IllegalArgumentException("Local address not an InetSocketAddress: " + 614 localAddr.getClass()); 615 } 616 InetSocketAddress inetAddr = (InetSocketAddress) localAddr; 617 addr = inetAddr.getAddress(); 618 if (addr == null) { 619 throw new SocketException("Host is unresolved: " + inetAddr.getHostName()); 620 } 621 localPort = inetAddr.getPort(); 622 checkListen(localPort); 623 } 624 impl.bind(localPort, addr); 625 isBound = true; 626 } 627 628 /** 629 * Connects this datagram socket to the remote host and port specified by 630 * {@code remoteAddr}. The host and port are validated, thereafter the only 631 * validation on {@code send()} and {@code receive()} is that the packet 632 * address/port matches the connected target. 633 * 634 * @param remoteAddr 635 * the address and port of the target host. 636 * @throws SocketException 637 * if an error occurs during connecting. 638 */ 639 public void connect(SocketAddress remoteAddr) throws SocketException { 640 if (remoteAddr == null) { 641 throw new IllegalArgumentException("remoteAddr == null"); 642 } 643 644 if (!(remoteAddr instanceof InetSocketAddress)) { 645 throw new IllegalArgumentException("Remote address not an InetSocketAddress: " + 646 remoteAddr.getClass()); 647 } 648 649 InetSocketAddress inetAddr = (InetSocketAddress) remoteAddr; 650 if (inetAddr.getAddress() == null) { 651 throw new SocketException("Host is unresolved: " + inetAddr.getHostName()); 652 } 653 654 synchronized (lock) { 655 // make sure the socket is open 656 checkClosedAndBind(true); 657 658 SecurityManager security = System.getSecurityManager(); 659 if (security != null) { 660 if (inetAddr.getAddress().isMulticastAddress()) { 661 security.checkMulticast(inetAddr.getAddress()); 662 } else { 663 security.checkConnect(inetAddr.getAddress().getHostName(), 664 inetAddr.getPort()); 665 } 666 } 667 668 // now try to do the connection at the native level. To be 669 // compatible for the case when the address is inaddr_any we just 670 // eat the exception an act as if we are connected at the java level 671 try { 672 impl.connect(inetAddr.getAddress(), inetAddr.getPort()); 673 } catch (Exception e) { 674 // not connected at the native level just do what we did before 675 } 676 677 // if we get here then we connected ok 678 address = inetAddr.getAddress(); 679 port = inetAddr.getPort(); 680 isConnected = true; 681 } 682 } 683 684 /** 685 * Determines whether the socket is bound to an address or not. 686 * 687 * @return {@code true} if the socket is bound, {@code false} otherwise. 688 */ 689 public boolean isBound() { 690 return isBound; 691 } 692 693 /** 694 * Determines whether the socket is connected to a target host. 695 * 696 * @return {@code true} if the socket is connected, {@code false} otherwise. 697 */ 698 public boolean isConnected() { 699 return isConnected; 700 } 701 702 /** 703 * Gets the address and port of the connected remote host. If this socket is 704 * not connected yet, {@code null} is returned. 705 * 706 * @return the remote socket address. 707 */ 708 public SocketAddress getRemoteSocketAddress() { 709 if (!isConnected()) { 710 return null; 711 } 712 return new InetSocketAddress(getInetAddress(), getPort()); 713 } 714 715 /** 716 * Gets the bound local address and port of this socket. If the socket is 717 * unbound, {@code null} is returned. 718 * 719 * @return the local socket address. 720 */ 721 public SocketAddress getLocalSocketAddress() { 722 if (!isBound()) { 723 return null; 724 } 725 return new InetSocketAddress(getLocalAddress(), getLocalPort()); 726 } 727 728 /** 729 * Sets the socket option {@code SocketOptions.SO_REUSEADDR}. This option 730 * has to be enabled if more than one UDP socket wants to be bound to the 731 * same address. That could be needed for receiving multicast packets. 732 * <p> 733 * There is an undefined behavior if this option is set after the socket is 734 * already bound. 735 * 736 * @param reuse 737 * the socket option value to enable or disable this option. 738 * @throws SocketException 739 * if the socket is closed or the option could not be set. 740 */ 741 public void setReuseAddress(boolean reuse) throws SocketException { 742 checkClosedAndBind(false); 743 impl.setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(reuse)); 744 } 745 746 /** 747 * Gets the state of the socket option {@code SocketOptions.SO_REUSEADDR}. 748 * 749 * @return {@code true} if the option is enabled, {@code false} otherwise. 750 * @throws SocketException 751 * if the socket is closed or the option is invalid. 752 */ 753 public boolean getReuseAddress() throws SocketException { 754 checkClosedAndBind(false); 755 return ((Boolean) impl.getOption(SocketOptions.SO_REUSEADDR)) 756 .booleanValue(); 757 } 758 759 /** 760 * Sets the socket option {@code SocketOptions.SO_BROADCAST}. This option 761 * must be enabled to send broadcast messages. 762 * 763 * @param broadcast 764 * the socket option value to enable or disable this option. 765 * @throws SocketException 766 * if the socket is closed or the option could not be set. 767 */ 768 public void setBroadcast(boolean broadcast) throws SocketException { 769 checkClosedAndBind(false); 770 impl.setOption(SocketOptions.SO_BROADCAST, Boolean.valueOf(broadcast)); 771 } 772 773 /** 774 * Gets the state of the socket option {@code SocketOptions.SO_BROADCAST}. 775 * 776 * @return {@code true} if the option is enabled, {@code false} otherwise. 777 * @throws SocketException 778 * if the socket is closed or the option is invalid. 779 */ 780 public boolean getBroadcast() throws SocketException { 781 checkClosedAndBind(false); 782 return ((Boolean) impl.getOption(SocketOptions.SO_BROADCAST)) 783 .booleanValue(); 784 } 785 786 /** 787 * Sets the {@see SocketOptions#IP_TOS} value for every packet sent by this socket. 788 * 789 * @throws SocketException 790 * if the socket is closed or the option could not be set. 791 */ 792 public void setTrafficClass(int value) throws SocketException { 793 checkClosedAndBind(false); 794 if (value < 0 || value > 255) { 795 throw new IllegalArgumentException(); 796 } 797 impl.setOption(SocketOptions.IP_TOS, Integer.valueOf(value)); 798 } 799 800 /** 801 * Returns this socket's {@see SocketOptions#IP_TOS} setting. 802 * 803 * @throws SocketException 804 * if the socket is closed or the option is invalid. 805 */ 806 public int getTrafficClass() throws SocketException { 807 checkClosedAndBind(false); 808 return (Integer) impl.getOption(SocketOptions.IP_TOS); 809 } 810 811 /** 812 * Gets the state of this socket. 813 * 814 * @return {@code true} if the socket is closed, {@code false} otherwise. 815 */ 816 public boolean isClosed() { 817 return isClosed; 818 } 819 820 /** 821 * Returns this socket's {@code DatagramChannel}, if one exists. A channel is 822 * available only if this socket wraps a channel. (That is, you can go from a 823 * channel to a socket and back again, but you can't go from an arbitrary socket to a channel.) 824 * In practice, this means that the socket must have been created by 825 * {@link java.nio.channels.DatagramChannel#open}. 826 */ 827 public DatagramChannel getChannel() { 828 return null; 829 } 830} 831