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