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 If there is an error closing the socket. 323 */ 324 public void disconnect() throws IOException { 325 closeQuietly(_socket_); 326 closeQuietly(_input_); 327 closeQuietly(_output_); 328 _socket_ = null; 329 _hostname_ = null; 330 _input_ = null; 331 _output_ = null; 332 } 333 334 /** 335 * If there are any listeners, send them the command details. 336 * 337 * @param command the command name 338 * @param message the complete message, including command name 339 * @since 3.0 340 */ 341 protected void fireCommandSent(final String command, final String message) { 342 if (getCommandSupport().getListenerCount() > 0) { 343 getCommandSupport().fireCommandSent(command, message); 344 } 345 } 346 347 /** 348 * If there are any listeners, send them the reply details. 349 * 350 * @param replyCode the code extracted from the reply 351 * @param reply the full reply text 352 * @since 3.0 353 */ 354 protected void fireReplyReceived(final int replyCode, final String reply) { 355 if (getCommandSupport().getListenerCount() > 0) { 356 getCommandSupport().fireReplyReceived(replyCode, reply); 357 } 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 * Returns 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 * Returns 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 * Returns 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 * Returns 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 * Returns 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 * @return The remote address to which the client is connected. Delegates to {@link Socket#getInetAddress()} 473 * @throws NullPointerException if the socket is not currently open 474 */ 475 public InetAddress getRemoteAddress() { 476 return _socket_.getInetAddress(); 477 } 478 479 /** 480 * Gets the remote socket address used for the connection. 481 * 482 * @return the remote socket address used for the connection 483 * @since 3.10.0 484 */ 485 protected InetSocketAddress getRemoteInetSocketAddress() { 486 return remoteInetSocketAddress; 487 } 488 489 /** 490 * Returns the port number of the remote host to which the client is connected. Delegates to {@link Socket#getPort()} 491 * 492 * @return The port number of the remote host to which the client is connected. 493 * @throws NullPointerException if the socket is not currently open 494 */ 495 public int getRemotePort() { 496 return _socket_.getPort(); 497 } 498 499 /** 500 * Gets the current sendBuffer size 501 * 502 * @return the size, or -1 if not initialized 503 * @since 3.0 504 */ 505 protected int getSendBufferSize() { 506 return sendBufferSize; 507 } 508 509 /** 510 * Gets the underlying {@link ServerSocketFactory} 511 * 512 * @return The server socket factory 513 * @since 2.2 514 */ 515 public ServerSocketFactory getServerSocketFactory() { 516 return _serverSocketFactory_; 517 } 518 519 /** 520 * Returns the current SO_LINGER timeout of the currently opened socket. 521 * 522 * @return The current SO_LINGER timeout. If SO_LINGER is disabled returns -1. 523 * @throws SocketException If the operation fails. 524 * @throws NullPointerException if the socket is not currently open 525 */ 526 public int getSoLinger() throws SocketException { 527 return _socket_.getSoLinger(); 528 } 529 530 /** 531 * Returns the timeout in milliseconds of the currently opened socket. 532 * 533 * @return The timeout in milliseconds of the currently opened socket. 534 * @throws SocketException If the operation fails. 535 * @throws NullPointerException if the socket is not currently open 536 */ 537 public int getSoTimeout() throws SocketException { 538 return _socket_.getSoTimeout(); 539 } 540 541 /** 542 * Returns true if Nagle's algorithm is enabled on the currently opened socket. 543 * 544 * @return True if Nagle's algorithm is enabled on the currently opened socket, false otherwise. 545 * @throws SocketException If the operation fails. 546 * @throws NullPointerException if the socket is not currently open 547 */ 548 public boolean getTcpNoDelay() throws SocketException { 549 return _socket_.getTcpNoDelay(); 550 } 551 552 /** 553 * 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. 554 * 555 * @see <a href="https://issues.apache.org/jira/browse/NET-350">NET-350</a> 556 * @return {@code true} if the socket appears to be available for use 557 * @since 3.0 558 */ 559 @SuppressWarnings("resource") 560 public boolean isAvailable() { 561 if (isConnected()) { 562 try { 563 if (_socket_.getInetAddress() == null) { 564 return false; 565 } 566 if (_socket_.getPort() == 0) { 567 return false; 568 } 569 if (_socket_.getRemoteSocketAddress() == null) { 570 return false; 571 } 572 if (_socket_.isClosed()) { 573 return false; 574 } 575 /* 576 * 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: 577 */ 578 if (_socket_.isInputShutdown()) { 579 return false; 580 } 581 if (_socket_.isOutputShutdown()) { 582 return false; 583 } 584 /* ignore the result, catch exceptions: */ 585 // No need to close 586 _socket_.getInputStream(); 587 // No need to close 588 _socket_.getOutputStream(); 589 } catch (final IOException ioex) { 590 return false; 591 } 592 return true; 593 } 594 return false; 595 } 596 597 /** 598 * Returns true if the client is currently connected to a server. 599 * 600 * Delegates to {@link Socket#isConnected()} 601 * 602 * @return True if the client is currently connected to a server, false otherwise. 603 */ 604 public boolean isConnected() { 605 if (_socket_ == null) { 606 return false; 607 } 608 609 return _socket_.isConnected(); 610 } 611 612 /** 613 * Removes a ProtocolCommandListener. 614 * 615 * @param listener The ProtocolCommandListener to remove. 616 * @since 3.0 617 */ 618 public void removeProtocolCommandListener(final ProtocolCommandListener listener) { 619 getCommandSupport().removeProtocolCommandListener(listener); 620 } 621 622 /** 623 * Sets the charset. 624 * 625 * @param charset the charset. 626 * @since 3.3 627 */ 628 public void setCharset(final Charset charset) { 629 this.charset = charset; 630 } 631 632 /** 633 * Sets the connection timeout in milliseconds, which will be passed to the {@link Socket} object's connect() method. 634 * 635 * @param connectTimeout The connection timeout to use (in ms) 636 * @since 2.0 637 */ 638 public void setConnectTimeout(final int connectTimeout) { 639 this.connectTimeout = connectTimeout; 640 } 641 642 /** 643 * Sets the default port the SocketClient should connect to when a port is not specified. The {@link #_defaultPort_ _defaultPort_ } variable stores this 644 * value. If never set, the default port is equal to zero. 645 * 646 * @param port The default port to set. 647 */ 648 public void setDefaultPort(final int port) { 649 _defaultPort_ = port; 650 } 651 652 /** 653 * 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 654 * should not be confused with {@link #setSoTimeout setSoTimeout()} which operates on the currently opened socket. _timeout_ contains the new timeout value. 655 * 656 * @param timeout The timeout in milliseconds to use for the socket connection. 657 */ 658 public void setDefaultTimeout(final int timeout) { 659 _timeout_ = timeout; 660 } 661 662 /** 663 * Sets the SO_KEEPALIVE flag on the currently opened socket. 664 * 665 * From the Javadocs, the default keepalive time is 2 hours (although this is implementation dependent). It looks as though the Windows WSA sockets 666 * implementation allows a specific keepalive value to be set, although this seems not to be the case on other systems. 667 * 668 * @param keepAlive If true, keepAlive is turned on 669 * @throws SocketException if there is a problem with the socket 670 * @throws NullPointerException if the socket is not currently open 671 * @since 2.2 672 */ 673 public void setKeepAlive(final boolean keepAlive) throws SocketException { 674 _socket_.setKeepAlive(keepAlive); 675 } 676 677 /** 678 * Sets the proxy for use with all the connections. The proxy is used for connections established after the call to this method. 679 * 680 * @param proxy the new proxy for connections. 681 * @since 3.2 682 */ 683 public void setProxy(final Proxy proxy) { 684 setSocketFactory(new DefaultSocketFactory(proxy)); 685 connProxy = proxy; 686 } 687 688 /** 689 * Sets the underlying socket receive buffer size. 690 * 691 * @param size The size of the buffer in bytes. 692 * @throws SocketException never (but subclasses may wish to do so) 693 * @since 2.0 694 */ 695 public void setReceiveBufferSize(final int size) throws SocketException { 696 receiveBufferSize = size; 697 } 698 699 /** 700 * Sets the underlying socket send buffer size. 701 * 702 * @param size The size of the buffer in bytes. 703 * @throws SocketException never thrown, but subclasses might want to do so 704 * @since 2.0 705 */ 706 public void setSendBufferSize(final int size) throws SocketException { 707 sendBufferSize = size; 708 } 709 710 /** 711 * Sets the ServerSocketFactory used by the SocketClient to open ServerSocket connections. If the factory value is null, then a default factory is used 712 * (only do this to reset the factory after having previously altered it). 713 * 714 * @param factory The new ServerSocketFactory the SocketClient should use. 715 * @since 2.0 716 */ 717 public void setServerSocketFactory(final ServerSocketFactory factory) { 718 if (factory == null) { 719 _serverSocketFactory_ = DEFAULT_SERVER_SOCKET_FACTORY; 720 } else { 721 _serverSocketFactory_ = factory; 722 } 723 } 724 725 /** 726 * 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 727 * reset the factory after having previously altered it). Any proxy setting is discarded. 728 * 729 * @param factory The new SocketFactory the SocketClient should use. 730 */ 731 public void setSocketFactory(final SocketFactory factory) { 732 if (factory == null) { 733 _socketFactory_ = DEFAULT_SOCKET_FACTORY; 734 } else { 735 _socketFactory_ = factory; 736 } 737 } 738 739 /** 740 * Sets the SO_LINGER timeout on the currently opened socket. 741 * 742 * @param on True if linger is to be enabled, false if not. 743 * @param val The {@code linger} timeout (in hundredths of a second?) 744 * @throws SocketException If the operation fails. 745 * @throws NullPointerException if the socket is not currently open 746 */ 747 public void setSoLinger(final boolean on, final int val) throws SocketException { 748 _socket_.setSoLinger(on, val); 749 } 750 751 /** 752 * Sets the timeout in milliseconds of a currently open connection. Only call this method after a connection has been opened by {@link #connect connect()}. 753 * <p> 754 * To set the initial timeout, use {@link #setDefaultTimeout(int)} instead. 755 * 756 * @param timeout The timeout in milliseconds to use for the currently open socket connection. 757 * @throws SocketException If the operation fails. 758 * @throws NullPointerException if the socket is not currently open 759 */ 760 public void setSoTimeout(final int timeout) throws SocketException { 761 _socket_.setSoTimeout(timeout); 762 } 763 764 /** 765 * Enables or disables the Nagle's algorithm (TCP_NODELAY) on the currently opened socket. 766 * 767 * @param on True if Nagle's algorithm is to be enabled, false if not. 768 * @throws SocketException If the operation fails. 769 * @throws NullPointerException if the socket is not currently open 770 */ 771 public void setTcpNoDelay(final boolean on) throws SocketException { 772 _socket_.setTcpNoDelay(on); 773 } 774 775 /** 776 * 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 777 * 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 778 * stream. 779 * 780 * @param socket the item to check against 781 * @return True if the remote hosts are the same, false if not. 782 */ 783 public boolean verifyRemote(final Socket socket) { 784 final InetAddress host1; 785 final InetAddress host2; 786 787 host1 = socket.getInetAddress(); 788 host2 = getRemoteAddress(); 789 790 return host1.equals(host2); 791 } 792 793 /* 794 * 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 795 * methods which were moved here. 796 */ 797}