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