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 Socket in textual presentation. 065 * 066 * @param socket the socket to query. 067 * @return the raw IP address in a string format. 068 * @since 3.12.0 069 */ 070 protected static String getHostAddress(final Socket socket) { 071 return getHostAddress(socket.getInetAddress()); 072 } 073 074 /** 075 * Gets the IP address string of the given InetAddress in textual presentation. 076 * 077 * @param inetAddress Internet Protocol (IP) address to query. 078 * @return the raw IP address in a string format. 079 * @since 3.12.0 080 */ 081 protected static String getHostAddress(final InetAddress inetAddress) { 082 return inetAddress != null ? inetAddress.getHostAddress() : null; 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 ms) 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) { 566 return false; 567 } 568 if (_socket_.getPort() == 0) { 569 return false; 570 } 571 if (_socket_.getRemoteSocketAddress() == null) { 572 return false; 573 } 574 if (_socket_.isClosed()) { 575 return false; 576 } 577 /* 578 * 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: 579 */ 580 if (_socket_.isInputShutdown()) { 581 return false; 582 } 583 if (_socket_.isOutputShutdown()) { 584 return false; 585 } 586 /* ignore the result, catch exceptions: */ 587 // No need to close 588 _socket_.getInputStream(); 589 // No need to close 590 _socket_.getOutputStream(); 591 } catch (final IOException ioex) { 592 return false; 593 } 594 return true; 595 } 596 return false; 597 } 598 599 /** 600 * Tests whether the client is currently connected to a server. 601 * 602 * Delegates to {@link Socket#isConnected()} 603 * 604 * @return True if the client is currently connected to a server, false otherwise. 605 */ 606 public boolean isConnected() { 607 if (_socket_ == null) { 608 return false; 609 } 610 611 return _socket_.isConnected(); 612 } 613 614 /** 615 * Removes a ProtocolCommandListener. 616 * 617 * @param listener The ProtocolCommandListener to remove. 618 * @since 3.0 619 */ 620 public void removeProtocolCommandListener(final ProtocolCommandListener listener) { 621 getCommandSupport().removeProtocolCommandListener(listener); 622 } 623 624 /** 625 * Sets the charset. 626 * 627 * @param charset the charset. 628 * @since 3.3 629 */ 630 public void setCharset(final Charset charset) { 631 this.charset = charset; 632 } 633 634 /** 635 * Sets the connection timeout in milliseconds, which will be passed to the {@link Socket} object's connect() method. 636 * 637 * @param connectTimeout The connection timeout to use (in ms) 638 * @since 2.0 639 */ 640 public void setConnectTimeout(final int connectTimeout) { 641 this.connectTimeout = connectTimeout; 642 } 643 644 /** 645 * Sets the default port the SocketClient should connect to when a port is not specified. The {@link #_defaultPort_ _defaultPort_} variable stores this 646 * value. If never set, the default port is equal to zero. 647 * 648 * @param port The default port to set. 649 */ 650 public void setDefaultPort(final int port) { 651 _defaultPort_ = port; 652 } 653 654 /** 655 * 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 656 * should not be confused with {@link #setSoTimeout setSoTimeout()} which operates on the currently opened socket. _timeout_ contains the new timeout value. 657 * 658 * @param timeout The timeout in milliseconds to use for the socket connection. 659 */ 660 public void setDefaultTimeout(final int timeout) { 661 _timeout_ = timeout; 662 } 663 664 /** 665 * Sets the SO_KEEPALIVE flag on the currently opened socket. 666 * 667 * From the Javadocs, the default keepalive time is 2 hours (although this is implementation dependent). It looks as though the Windows WSA sockets 668 * implementation allows a specific keepalive value to be set, although this seems not to be the case on other systems. 669 * 670 * @param keepAlive If true, keepAlive is turned on 671 * @throws SocketException if there is a problem with the socket 672 * @throws NullPointerException if the socket is not currently open 673 * @since 2.2 674 */ 675 public void setKeepAlive(final boolean keepAlive) throws SocketException { 676 _socket_.setKeepAlive(keepAlive); 677 } 678 679 /** 680 * Sets the proxy for use with all the connections. The proxy is used for connections established after the call to this method. 681 * 682 * @param proxy the new proxy for connections. 683 * @since 3.2 684 */ 685 public void setProxy(final Proxy proxy) { 686 setSocketFactory(new DefaultSocketFactory(proxy)); 687 connProxy = proxy; 688 } 689 690 /** 691 * Sets the underlying socket receive buffer size. 692 * 693 * @param size The size of the buffer in bytes. 694 * @throws SocketException never (but subclasses may wish to do so) 695 * @since 2.0 696 */ 697 @SuppressWarnings("unused") // subclasses may throw SocketException 698 public void setReceiveBufferSize(final int size) throws SocketException { 699 receiveBufferSize = size; 700 } 701 702 /** 703 * Sets the underlying socket send buffer size. 704 * 705 * @param size The size of the buffer in bytes. 706 * @throws SocketException never thrown, but subclasses might want to do so 707 * @since 2.0 708 */ 709 @SuppressWarnings("unused") // subclasses may throw SocketException 710 public void setSendBufferSize(final int size) throws SocketException { 711 sendBufferSize = size; 712 } 713 714 /** 715 * Sets the ServerSocketFactory used by the SocketClient to open ServerSocket connections. If the factory value is null, then a default factory is used 716 * (only do this to reset the factory after having previously altered it). 717 * 718 * @param factory The new ServerSocketFactory the SocketClient should use. 719 * @since 2.0 720 */ 721 public void setServerSocketFactory(final ServerSocketFactory factory) { 722 if (factory == null) { 723 _serverSocketFactory_ = DEFAULT_SERVER_SOCKET_FACTORY; 724 } else { 725 _serverSocketFactory_ = factory; 726 } 727 } 728 729 /** 730 * 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 731 * reset the factory after having previously altered it). Any proxy setting is discarded. 732 * 733 * @param factory The new SocketFactory the SocketClient should use. 734 */ 735 public void setSocketFactory(final SocketFactory factory) { 736 if (factory == null) { 737 _socketFactory_ = DEFAULT_SOCKET_FACTORY; 738 } else { 739 _socketFactory_ = factory; 740 } 741 } 742 743 /** 744 * Sets the SO_LINGER timeout on the currently opened socket. 745 * 746 * @param on True if linger is to be enabled, false if not. 747 * @param val The {@code linger} timeout (in hundredths of a second?) 748 * @throws SocketException If the operation fails. 749 * @throws NullPointerException if the socket is not currently open 750 */ 751 public void setSoLinger(final boolean on, final int val) throws SocketException { 752 _socket_.setSoLinger(on, val); 753 } 754 755 /** 756 * Sets the timeout in milliseconds of a currently open connection. Only call this method after a connection has been opened by {@link #connect connect()}. 757 * <p> 758 * To set the initial timeout, use {@link #setDefaultTimeout(int)} instead. 759 * 760 * @param timeout The timeout in milliseconds to use for the currently open socket connection. 761 * @throws SocketException If the operation fails. 762 * @throws NullPointerException if the socket is not currently open 763 */ 764 public void setSoTimeout(final int timeout) throws SocketException { 765 _socket_.setSoTimeout(timeout); 766 } 767 768 /** 769 * Enables or disables the Nagle's algorithm (TCP_NODELAY) on the currently opened socket. 770 * 771 * @param on True if Nagle's algorithm is to be enabled, false if not. 772 * @throws SocketException If the operation fails. 773 * @throws NullPointerException if the socket is not currently open 774 */ 775 public void setTcpNoDelay(final boolean on) throws SocketException { 776 _socket_.setTcpNoDelay(on); 777 } 778 779 /** 780 * 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 781 * 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 782 * stream. 783 * 784 * @param socket the item to check against 785 * @return True if the remote hosts are the same, false if not. 786 */ 787 public boolean verifyRemote(final Socket socket) { 788 return socket != null && Objects.equals(socket.getInetAddress(), getRemoteAddress()); 789 } 790 791 /* 792 * 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 793 * methods which were moved here. 794 */ 795}