001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.net; 019 020import java.io.Closeable; 021import java.io.IOException; 022import java.io.InputStream; 023import java.io.OutputStream; 024import java.net.InetAddress; 025import java.net.InetSocketAddress; 026import java.net.Proxy; 027import java.net.Socket; 028import java.net.SocketException; 029import java.nio.charset.Charset; 030 031import javax.net.ServerSocketFactory; 032import javax.net.SocketFactory; 033 034/** 035 * The SocketClient provides the basic operations that are required of client objects accessing sockets. It is meant to be subclassed to avoid having to rewrite 036 * the same code over and over again to open a socket, close a socket, set timeouts, etc. Of special note is the {@link #setSocketFactory setSocketFactory } 037 * method, which allows you to control the type of Socket the SocketClient creates for initiating network connections. This is especially useful for adding SSL 038 * or proxy support as well as better support for applets. For example, you could create a {@link javax.net.SocketFactory} that requests browser security 039 * capabilities before creating a socket. All classes derived from SocketClient should use the {@link #_socketFactory_ _socketFactory_ } member variable to 040 * create Socket and ServerSocket instances rather than instantiating them by directly invoking a constructor. By honoring this contract you guarantee that a 041 * user will always be able to provide his own Socket implementations by substituting his own SocketFactory. 042 * 043 * @see SocketFactory 044 */ 045public abstract class SocketClient { 046 /** 047 * The end of line character sequence used by most IETF protocols. That is a carriage return followed by a newline: "\r\n" 048 */ 049 public static final String NETASCII_EOL = "\r\n"; 050 051 /** The default SocketFactory shared by all SocketClient instances. */ 052 private static final SocketFactory DEFAULT_SOCKET_FACTORY = SocketFactory.getDefault(); 053 054 /** The default {@link ServerSocketFactory} */ 055 private static final ServerSocketFactory DEFAULT_SERVER_SOCKET_FACTORY = ServerSocketFactory.getDefault(); 056 057 /** The socket's connect timeout (0 = infinite timeout) */ 058 private static final int DEFAULT_CONNECT_TIMEOUT = 60000; 059 060 /** 061 * A ProtocolCommandSupport object used to manage the registering of ProtocolCommandListeners and the firing of ProtocolCommandEvents. 062 */ 063 private ProtocolCommandSupport commandSupport; 064 065 /** The timeout to use after opening a socket. */ 066 protected int _timeout_; 067 068 /** The socket used for the connection. */ 069 protected Socket _socket_; 070 071 /** The hostname used for the connection (null = no hostname supplied). */ 072 protected String _hostname_; 073 074 /** The default port the client should connect to. */ 075 protected int _defaultPort_; 076 077 /** The socket's InputStream. */ 078 protected InputStream _input_; 079 080 /** The socket's OutputStream. */ 081 protected OutputStream _output_; 082 083 /** The socket's SocketFactory. */ 084 protected SocketFactory _socketFactory_; 085 086 /** The socket's ServerSocket Factory. */ 087 protected ServerSocketFactory _serverSocketFactory_; 088 089 protected int connectTimeout = DEFAULT_CONNECT_TIMEOUT; 090 091 /** Hint for SO_RCVBUF size */ 092 private int receiveBufferSize = -1; 093 094 /** Hint for SO_SNDBUF size */ 095 private int sendBufferSize = -1; 096 097 /** The proxy to use when connecting. */ 098 private Proxy connProxy; 099 100 /** 101 * Charset to use for byte IO. 102 */ 103 private Charset charset = Charset.defaultCharset(); 104 105 /** 106 * Default constructor for SocketClient. Initializes _socket_ to null, _timeout_ to 0, _defaultPort to 0, _isConnected_ to false, charset to 107 * {@code Charset.defaultCharset()} and _socketFactory_ to a shared instance of {@link org.apache.commons.net.DefaultSocketFactory}. 108 */ 109 public SocketClient() { 110 _socket_ = null; 111 _hostname_ = null; 112 _input_ = null; 113 _output_ = null; 114 _timeout_ = 0; 115 _defaultPort_ = 0; 116 _socketFactory_ = DEFAULT_SOCKET_FACTORY; 117 _serverSocketFactory_ = DEFAULT_SERVER_SOCKET_FACTORY; 118 } 119 120 // helper method to allow code to be shared with connect(String,...) methods 121 private void _connect(final InetAddress host, final int port, final InetAddress localAddr, final int localPort) throws SocketException, IOException { 122 _socket_ = _socketFactory_.createSocket(); 123 if (receiveBufferSize != -1) { 124 _socket_.setReceiveBufferSize(receiveBufferSize); 125 } 126 if (sendBufferSize != -1) { 127 _socket_.setSendBufferSize(sendBufferSize); 128 } 129 if (localAddr != null) { 130 _socket_.bind(new InetSocketAddress(localAddr, localPort)); 131 } 132 _socket_.connect(new InetSocketAddress(host, port), connectTimeout); 133 _connectAction_(); 134 } 135 136 /** 137 * Because there are so many connect() methods, the _connectAction_() method is provided as a means of performing some action immediately after establishing 138 * a connection, rather than reimplementing all of the connect() methods. The last action performed by every connect() method after opening a socket is to 139 * call this method. 140 * <p> 141 * This method sets the timeout on the just opened socket to the default timeout set by {@link #setDefaultTimeout setDefaultTimeout() }, sets _input_ and 142 * _output_ to the socket's InputStream and OutputStream respectively, and sets _isConnected_ to true. 143 * <p> 144 * Subclasses overriding this method should start by calling <code> super._connectAction_() </code> first to ensure the initialization of the aforementioned 145 * protected variables. 146 * 147 * @throws IOException (SocketException) if a problem occurs with the socket 148 */ 149 protected void _connectAction_() throws IOException { 150 applySocketAttributes(); 151 _input_ = _socket_.getInputStream(); 152 _output_ = _socket_.getOutputStream(); 153 } 154 155 /** 156 * Adds a ProtocolCommandListener. 157 * 158 * @param listener The ProtocolCommandListener to add. 159 * @since 3.0 160 */ 161 public void addProtocolCommandListener(final ProtocolCommandListener listener) { 162 getCommandSupport().addProtocolCommandListener(listener); 163 } 164 165 /** 166 * Applies socket attributes. 167 * 168 * @throws SocketException if there is an error in the underlying protocol, such as a TCP error. 169 * @since 3.8.0 170 */ 171 protected void applySocketAttributes() throws SocketException { 172 _socket_.setSoTimeout(_timeout_); 173 } 174 175 private void closeQuietly(final Closeable close) { 176 if (close != null) { 177 try { 178 close.close(); 179 } catch (final IOException e) { 180 // Ignored 181 } 182 } 183 } 184 185 private void closeQuietly(final Socket socket) { 186 if (socket != null) { 187 try { 188 socket.close(); 189 } catch (final IOException e) { 190 // Ignored 191 } 192 } 193 } 194 195 /** 196 * Opens a Socket connected to a remote host at the current default port and originating from the current host at a system assigned port. Before returning, 197 * {@link #_connectAction_ _connectAction_() } is called to perform connection initialization actions. 198 * 199 * @param host The remote host. 200 * @throws SocketException If the socket timeout could not be set. 201 * @throws IOException If the socket could not be opened. In most cases you will only want to catch IOException since SocketException is derived from 202 * it. 203 */ 204 public void connect(final InetAddress host) throws SocketException, IOException { 205 _hostname_ = null; 206 connect(host, _defaultPort_); 207 } 208 209 /** 210 * Opens a Socket connected to a remote host at the specified port and originating from the current host at a system assigned port. Before returning, 211 * {@link #_connectAction_ _connectAction_() } is called to perform connection initialization actions. 212 * 213 * @param host The remote host. 214 * @param port The port to connect to on the remote host. 215 * @throws SocketException If the socket timeout could not be set. 216 * @throws IOException If the socket could not be opened. In most cases you will only want to catch IOException since SocketException is derived from 217 * it. 218 */ 219 public void connect(final InetAddress host, final int port) throws SocketException, IOException { 220 _hostname_ = null; 221 _connect(host, port, null, -1); 222 } 223 224 /** 225 * Opens a Socket connected to a remote host at the specified port and originating from the specified local address and port. Before returning, 226 * {@link #_connectAction_ _connectAction_() } is called to perform connection initialization actions. 227 * 228 * @param host The remote host. 229 * @param port The port to connect to on the remote host. 230 * @param localAddr The local address to use. 231 * @param localPort The local port to use. 232 * @throws SocketException If the socket timeout could not be set. 233 * @throws IOException If the socket could not be opened. In most cases you will only want to catch IOException since SocketException is derived from 234 * it. 235 */ 236 public void connect(final InetAddress host, final int port, final InetAddress localAddr, final int localPort) throws SocketException, IOException { 237 _hostname_ = null; 238 _connect(host, port, localAddr, localPort); 239 } 240 241 /** 242 * Opens a Socket connected to a remote host at the current default port and originating from the current host at a system assigned port. Before returning, 243 * {@link #_connectAction_ _connectAction_() } is called to perform connection initialization actions. 244 * 245 * @param hostname The name of the remote host. 246 * @throws SocketException If the socket timeout could not be set. 247 * @throws IOException If the socket could not be opened. In most cases you will only want to catch IOException since SocketException is 248 * derived from it. 249 * @throws java.net.UnknownHostException If the hostname cannot be resolved. 250 */ 251 public void connect(final String hostname) throws SocketException, IOException { 252 connect(hostname, _defaultPort_); 253 } 254 255 /** 256 * Opens a Socket connected to a remote host at the specified port and originating from the current host at a system assigned port. Before returning, 257 * {@link #_connectAction_ _connectAction_() } is called to perform connection initialization actions. 258 * 259 * @param hostname The name of the remote host. 260 * @param port The port to connect to on the remote host. 261 * @throws SocketException If the socket timeout could not be set. 262 * @throws IOException If the socket could not be opened. In most cases you will only want to catch IOException since SocketException is 263 * derived from it. 264 * @throws java.net.UnknownHostException If the hostname cannot be resolved. 265 */ 266 public void connect(final String hostname, final int port) throws SocketException, IOException { 267 _hostname_ = hostname; 268 _connect(InetAddress.getByName(hostname), port, null, -1); 269 } 270 271 /** 272 * Opens a Socket connected to a remote host at the specified port and originating from the specified local address and port. Before returning, 273 * {@link #_connectAction_ _connectAction_() } is called to perform connection initialization actions. 274 * 275 * @param hostname The name of the remote host. 276 * @param port The port to connect to on the remote host. 277 * @param localAddr The local address to use. 278 * @param localPort The local port to use. 279 * @throws SocketException If the socket timeout could not be set. 280 * @throws IOException If the socket could not be opened. In most cases you will only want to catch IOException since SocketException is 281 * derived from it. 282 * @throws java.net.UnknownHostException If the hostname cannot be resolved. 283 */ 284 public void connect(final String hostname, final int port, final InetAddress localAddr, final int localPort) throws SocketException, IOException { 285 _hostname_ = hostname; 286 _connect(InetAddress.getByName(hostname), port, localAddr, localPort); 287 } 288 289 /** 290 * Create the CommandSupport instance if required 291 */ 292 protected void createCommandSupport() { 293 commandSupport = new ProtocolCommandSupport(this); 294 } 295 296 /** 297 * Disconnects the socket connection. You should call this method after you've finished using the class instance and also before you call {@link #connect 298 * connect() } again. _isConnected_ is set to false, _socket_ is set to null, _input_ is set to null, and _output_ is set to null. 299 * 300 * @throws IOException If there is an error closing the socket. 301 */ 302 public void disconnect() throws IOException { 303 closeQuietly(_socket_); 304 closeQuietly(_input_); 305 closeQuietly(_output_); 306 _socket_ = null; 307 _hostname_ = null; 308 _input_ = null; 309 _output_ = null; 310 } 311 312 /** 313 * If there are any listeners, send them the command details. 314 * 315 * @param command the command name 316 * @param message the complete message, including command name 317 * @since 3.0 318 */ 319 protected void fireCommandSent(final String command, final String message) { 320 if (getCommandSupport().getListenerCount() > 0) { 321 getCommandSupport().fireCommandSent(command, message); 322 } 323 } 324 325 /** 326 * If there are any listeners, send them the reply details. 327 * 328 * @param replyCode the code extracted from the reply 329 * @param reply the full reply text 330 * @since 3.0 331 */ 332 protected void fireReplyReceived(final int replyCode, final String reply) { 333 if (getCommandSupport().getListenerCount() > 0) { 334 getCommandSupport().fireReplyReceived(replyCode, reply); 335 } 336 } 337 338 /** 339 * Gets the charset. 340 * 341 * @return the charset. 342 * @since 3.3 343 */ 344 public Charset getCharset() { 345 return charset; 346 } 347 348 /** 349 * Gets the charset name. 350 * 351 * @return the charset. 352 * @since 3.3 353 * @deprecated Since the code now requires Java 1.6 as a mininmum 354 */ 355 @Deprecated 356 public String getCharsetName() { 357 return charset.name(); 358 } 359 360 /** 361 * Subclasses can override this if they need to provide their own instance field for backwards compatibilty. 362 * 363 * @return the CommandSupport instance, may be {@code null} 364 * @since 3.0 365 */ 366 protected ProtocolCommandSupport getCommandSupport() { 367 return commandSupport; 368 } 369 370 /** 371 * Get the underlying socket connection timeout. 372 * 373 * @return timeout (in ms) 374 * @since 2.0 375 */ 376 public int getConnectTimeout() { 377 return connectTimeout; 378 } 379 380 /** 381 * Returns the current value of the default port (stored in {@link #_defaultPort_ _defaultPort_ }). 382 * 383 * @return The current value of the default port. 384 */ 385 public int getDefaultPort() { 386 return _defaultPort_; 387 } 388 389 /** 390 * Returns the default timeout in milliseconds that is used when opening a socket. 391 * 392 * @return The default timeout in milliseconds that is used when opening a socket. 393 */ 394 public int getDefaultTimeout() { 395 return _timeout_; 396 } 397 398 /** 399 * Returns the current value of the SO_KEEPALIVE flag on the currently opened socket. Delegates to {@link Socket#getKeepAlive()} 400 * 401 * @return True if SO_KEEPALIVE is enabled. 402 * @throws SocketException if there is a problem with the socket 403 * @throws NullPointerException if the socket is not currently open 404 * @since 2.2 405 */ 406 public boolean getKeepAlive() throws SocketException { 407 return _socket_.getKeepAlive(); 408 } 409 410 /** 411 * Returns the local address to which the client's socket is bound. Delegates to {@link Socket#getLocalAddress()} 412 * 413 * @return The local address to which the client's socket is bound. 414 * @throws NullPointerException if the socket is not currently open 415 */ 416 public InetAddress getLocalAddress() { 417 return _socket_.getLocalAddress(); 418 } 419 420 /** 421 * Returns the port number of the open socket on the local host used for the connection. Delegates to {@link Socket#getLocalPort()} 422 * 423 * @return The port number of the open socket on the local host used for the connection. 424 * @throws NullPointerException if the socket is not currently open 425 */ 426 public int getLocalPort() { 427 return _socket_.getLocalPort(); 428 } 429 430 /** 431 * Gets the proxy for use with all the connections. 432 * 433 * @return the current proxy for connections. 434 */ 435 public Proxy getProxy() { 436 return connProxy; 437 } 438 439 /** 440 * Get the current receivedBuffer size 441 * 442 * @return the size, or -1 if not initialized 443 * @since 3.0 444 */ 445 protected int getReceiveBufferSize() { 446 return receiveBufferSize; 447 } 448 449 /** 450 * @return The remote address to which the client is connected. Delegates to {@link Socket#getInetAddress()} 451 * @throws NullPointerException if the socket is not currently open 452 */ 453 public InetAddress getRemoteAddress() { 454 return _socket_.getInetAddress(); 455 } 456 457 /** 458 * Returns the port number of the remote host to which the client is connected. Delegates to {@link Socket#getPort()} 459 * 460 * @return The port number of the remote host to which the client is connected. 461 * @throws NullPointerException if the socket is not currently open 462 */ 463 public int getRemotePort() { 464 return _socket_.getPort(); 465 } 466 467 /** 468 * Get the current sendBuffer size 469 * 470 * @return the size, or -1 if not initialized 471 * @since 3.0 472 */ 473 protected int getSendBufferSize() { 474 return sendBufferSize; 475 } 476 477 /** 478 * Get the underlying {@link ServerSocketFactory} 479 * 480 * @return The server socket factory 481 * @since 2.2 482 */ 483 public ServerSocketFactory getServerSocketFactory() { 484 return _serverSocketFactory_; 485 } 486 487 /** 488 * Returns the current SO_LINGER timeout of the currently opened socket. 489 * 490 * @return The current SO_LINGER timeout. If SO_LINGER is disabled returns -1. 491 * @throws SocketException If the operation fails. 492 * @throws NullPointerException if the socket is not currently open 493 */ 494 public int getSoLinger() throws SocketException { 495 return _socket_.getSoLinger(); 496 } 497 498 /** 499 * Returns the timeout in milliseconds of the currently opened socket. 500 * 501 * @return The timeout in milliseconds of the currently opened socket. 502 * @throws SocketException If the operation fails. 503 * @throws NullPointerException if the socket is not currently open 504 */ 505 public int getSoTimeout() throws SocketException { 506 return _socket_.getSoTimeout(); 507 } 508 509 /** 510 * Returns true if Nagle's algorithm is enabled on the currently opened socket. 511 * 512 * @return True if Nagle's algorithm is enabled on the currently opened socket, false otherwise. 513 * @throws SocketException If the operation fails. 514 * @throws NullPointerException if the socket is not currently open 515 */ 516 public boolean getTcpNoDelay() throws SocketException { 517 return _socket_.getTcpNoDelay(); 518 } 519 520 /** 521 * Make various checks on the socket to test if it is available for use. Note that the only sure test is to use it, but these checks may help in some cases. 522 * 523 * @see <a href="https://issues.apache.org/jira/browse/NET-350">NET-350</a> 524 * @return {@code true} if the socket appears to be available for use 525 * @since 3.0 526 */ 527 @SuppressWarnings("resource") 528 public boolean isAvailable() { 529 if (isConnected()) { 530 try { 531 if (_socket_.getInetAddress() == null) { 532 return false; 533 } 534 if (_socket_.getPort() == 0) { 535 return false; 536 } 537 if (_socket_.getRemoteSocketAddress() == null) { 538 return false; 539 } 540 if (_socket_.isClosed()) { 541 return false; 542 } 543 /* 544 * these aren't exact checks (a Socket can be half-open), but since we usually require two-way data transfer, we check these here too: 545 */ 546 if (_socket_.isInputShutdown()) { 547 return false; 548 } 549 if (_socket_.isOutputShutdown()) { 550 return false; 551 } 552 /* ignore the result, catch exceptions: */ 553 // No need to close 554 _socket_.getInputStream(); 555 // No need to close 556 _socket_.getOutputStream(); 557 } catch (final IOException ioex) { 558 return false; 559 } 560 return true; 561 } 562 return false; 563 } 564 565 /** 566 * Returns true if the client is currently connected to a server. 567 * 568 * Delegates to {@link Socket#isConnected()} 569 * 570 * @return True if the client is currently connected to a server, false otherwise. 571 */ 572 public boolean isConnected() { 573 if (_socket_ == null) { 574 return false; 575 } 576 577 return _socket_.isConnected(); 578 } 579 580 /** 581 * Removes a ProtocolCommandListener. 582 * 583 * @param listener The ProtocolCommandListener to remove. 584 * @since 3.0 585 */ 586 public void removeProtocolCommandListener(final ProtocolCommandListener listener) { 587 getCommandSupport().removeProtocolCommandListener(listener); 588 } 589 590 /** 591 * Sets the charset. 592 * 593 * @param charset the charset. 594 * @since 3.3 595 */ 596 public void setCharset(final Charset charset) { 597 this.charset = charset; 598 } 599 600 /** 601 * Sets the connection timeout in milliseconds, which will be passed to the {@link Socket} object's connect() method. 602 * 603 * @param connectTimeout The connection timeout to use (in ms) 604 * @since 2.0 605 */ 606 public void setConnectTimeout(final int connectTimeout) { 607 this.connectTimeout = connectTimeout; 608 } 609 610 /** 611 * Sets the default port the SocketClient should connect to when a port is not specified. The {@link #_defaultPort_ _defaultPort_ } variable stores this 612 * value. If never set, the default port is equal to zero. 613 * 614 * @param port The default port to set. 615 */ 616 public void setDefaultPort(final int port) { 617 _defaultPort_ = port; 618 } 619 620 /** 621 * Set the default timeout in milliseconds to use when opening a socket. This value is only used previous to a call to {@link #connect connect()} and should 622 * not be confused with {@link #setSoTimeout setSoTimeout()} which operates on an the currently opened socket. _timeout_ contains the new timeout value. 623 * 624 * @param timeout The timeout in milliseconds to use for the socket connection. 625 */ 626 public void setDefaultTimeout(final int timeout) { 627 _timeout_ = timeout; 628 } 629 630 /** 631 * Sets the SO_KEEPALIVE flag on the currently opened socket. 632 * 633 * From the Javadocs, the default keepalive time is 2 hours (although this is implementation dependent). It looks as though the Windows WSA sockets 634 * implementation allows a specific keepalive value to be set, although this seems not to be the case on other systems. 635 * 636 * @param keepAlive If true, keepAlive is turned on 637 * @throws SocketException if there is a problem with the socket 638 * @throws NullPointerException if the socket is not currently open 639 * @since 2.2 640 */ 641 public void setKeepAlive(final boolean keepAlive) throws SocketException { 642 _socket_.setKeepAlive(keepAlive); 643 } 644 645 /** 646 * Sets the proxy for use with all the connections. The proxy is used for connections established after the call to this method. 647 * 648 * @param proxy the new proxy for connections. 649 * @since 3.2 650 */ 651 public void setProxy(final Proxy proxy) { 652 setSocketFactory(new DefaultSocketFactory(proxy)); 653 connProxy = proxy; 654 } 655 656 /** 657 * Sets the underlying socket receive buffer size. 658 * 659 * @param size The size of the buffer in bytes. 660 * @throws SocketException never (but subclasses may wish to do so) 661 * @since 2.0 662 */ 663 public void setReceiveBufferSize(final int size) throws SocketException { 664 receiveBufferSize = size; 665 } 666 667 /** 668 * Set the underlying socket send buffer size. 669 * 670 * @param size The size of the buffer in bytes. 671 * @throws SocketException never thrown, but subclasses might want to do so 672 * @since 2.0 673 */ 674 public void setSendBufferSize(final int size) throws SocketException { 675 sendBufferSize = size; 676 } 677 678 /** 679 * Sets the ServerSocketFactory used by the SocketClient to open ServerSocket connections. If the factory value is null, then a default factory is used 680 * (only do this to reset the factory after having previously altered it). 681 * 682 * @param factory The new ServerSocketFactory the SocketClient should use. 683 * @since 2.0 684 */ 685 public void setServerSocketFactory(final ServerSocketFactory factory) { 686 if (factory == null) { 687 _serverSocketFactory_ = DEFAULT_SERVER_SOCKET_FACTORY; 688 } else { 689 _serverSocketFactory_ = factory; 690 } 691 } 692 693 /** 694 * Sets the SocketFactory used by the SocketClient to open socket connections. If the factory value is null, then a default factory is used (only do this to 695 * reset the factory after having previously altered it). Any proxy setting is discarded. 696 * 697 * @param factory The new SocketFactory the SocketClient should use. 698 */ 699 public void setSocketFactory(final SocketFactory factory) { 700 if (factory == null) { 701 _socketFactory_ = DEFAULT_SOCKET_FACTORY; 702 } else { 703 _socketFactory_ = factory; 704 } 705 } 706 707 /** 708 * Sets the SO_LINGER timeout on the currently opened socket. 709 * 710 * @param on True if linger is to be enabled, false if not. 711 * @param val The linger timeout (in hundredths of a second?) 712 * @throws SocketException If the operation fails. 713 * @throws NullPointerException if the socket is not currently open 714 */ 715 public void setSoLinger(final boolean on, final int val) throws SocketException { 716 _socket_.setSoLinger(on, val); 717 } 718 719 /** 720 * Set the timeout in milliseconds of a currently open connection. Only call this method after a connection has been opened by {@link #connect connect()}. 721 * <p> 722 * To set the initial timeout, use {@link #setDefaultTimeout(int)} instead. 723 * 724 * @param timeout The timeout in milliseconds to use for the currently open socket connection. 725 * @throws SocketException If the operation fails. 726 * @throws NullPointerException if the socket is not currently open 727 */ 728 public void setSoTimeout(final int timeout) throws SocketException { 729 _socket_.setSoTimeout(timeout); 730 } 731 732 /** 733 * Enables or disables the Nagle's algorithm (TCP_NODELAY) on the currently opened socket. 734 * 735 * @param on True if Nagle's algorithm is to be enabled, false if not. 736 * @throws SocketException If the operation fails. 737 * @throws NullPointerException if the socket is not currently open 738 */ 739 public void setTcpNoDelay(final boolean on) throws SocketException { 740 _socket_.setTcpNoDelay(on); 741 } 742 743 /** 744 * Verifies that the remote end of the given socket is connected to the the same host that the SocketClient is currently connected to. This is useful for 745 * doing a quick security check when a client needs to accept a connection from a server, such as an FTP data connection or a BSD R command standard error 746 * stream. 747 * 748 * @param socket the item to check against 749 * @return True if the remote hosts are the same, false if not. 750 */ 751 public boolean verifyRemote(final Socket socket) { 752 final InetAddress host1; 753 final InetAddress host2; 754 755 host1 = socket.getInetAddress(); 756 host2 = getRemoteAddress(); 757 758 return host1.equals(host2); 759 } 760 761 /* 762 * N.B. Fields cannot be pulled up into a super-class without breaking binary compatibility, so the abstract method is needed to pass the instance to the 763 * methods which were moved here. 764 */ 765}