## Socket options

[SocketOptions] controls various low-level parameters related to TCP connections between the driver and Cassandra.

You can provide these when initializing the cluster:

```java
Cluster cluster = Cluster.builder()
        .addContactPoint("127.0.0.1")
        .withSocketOptions(
                new SocketOptions()
                        .setConnectTimeoutMillis(2000))
        .build();
```

If you don't, the driver uses a default configuration (see the javadocs of the setter methods of [SocketOptions] for the
default values).

You can retrieve and change the options at runtime:

```java
SocketOptions socketOptions = cluster.getConfiguration().getSocketOptions();
socketOptions.setConnectTimeoutMillis(3000);
```

* changes to the [read timeout](#driver-read-timeout) will be taken into account for future request executions;
* changes to any other option will be taken into account for future connections (connections that were already opened at
  the time of the change are unaffected, they keep the old values).

### TCP options

[setConnectTimeoutMillis] defines how long the driver waits to establish a new connection to a Cassandra node before
giving up.

Other options control the usual low-level TCP parameters (refer to their individual javadoc for details):
[setKeepAlive], [setReceiveBufferSize], [setReuseAddress], [setSendBufferSize], [setSoLinger], [setTcpNoDelay]. Most of
these options are not set explicitly by the driver, so they get the default value from the underlying TCP transport.
One exception is `setTcpNoDelay`, which is forced to `true` (meaning that Nagle's algorithm is *disabled* for driver
connections).

### Driver read timeout

[setReadTimeoutMillis] controls how long the driver waits for a response *from a given Cassandra node* before
considering it unresponsive.

Cassandra normally provides a guaranteed response time for each type of query, as shown by these parameters in
`cassandra.yaml` (here with their default values):

```yaml
counter_write_request_timeout_in_ms: 5000
range_request_timeout_in_ms: 10000
read_request_timeout_in_ms: 5000
request_timeout_in_ms: 10000
truncate_request_timeout_in_ms: 60000
write_request_timeout_in_ms: 2000
```

The goal of `setReadTimeoutMillis` is to give up on a node if it took longer than these thresholds to reply, on the
assumption that there's probably something wrong with it. Therefore it should be set **higher than the server-side
timeouts**. The default value is **12 seconds** (lower than `truncate_request_timeout_in_ms`, but we consider `TRUNCATE`
queries as maintenance operations that shouldn't be run from your application). Do not set it too low, or the driver
might give up on requests that had a chance of succeeding.

If the timeout is reached, the driver will receive an `OperationTimedOutException` and retry the query on the next node
in the [query plan](../load_balancing/#query-plan).

#### Limiting overall query time

It should be clear by now that `setReadTimeoutMillis` is *per node*, not per query. If the driver retries on 4 different
nodes, the overall execution time could theoretically be up to 4 times the read timeout. If you want a per query timeout,
use the following pattern:

```java
import com.google.common.base.Throwables;

ResultSet execute(Statement statement, long timeout, TimeUnit unit)
        throws InterruptedException, TimeoutException {
    ResultSetFuture future = session.executeAsync(statement);
    try {
        return future.get(timeout, unit);
    } catch (ExecutionException e) {
        throw Throwables.propagate(e.getCause());
    } catch (TimeoutException e) {
        future.cancel(true);
        throw e;
    }
}
```

A complementary approach is to enable [speculative executions](../speculative_execution/), to have the driver query
multiple nodes in parallel. This way you won't have to wait for the full timeout if the first node is unresponsive.

#### Driver read timeout vs. server read timeout

Unfortunately, the term "read timeout" clashes with another concept that is not directly related: a Cassandra node may
reply with a [READ_TIMEOUT](../retries/#on-read-timeout) error when it didn't hear back from enough replicas during a
read query.

To clarify:

* **driver read timeout:** the driver did not receive any response from the current coordinator within
  `SocketOptions.setReadTimeoutMillis`. It retries the query on the next node.
* **server read timeout:** the driver *did* receive a response, but that response indicates that the coordinator timed
  out while waiting for other replicas. It invokes [onReadTimeout] on the [retry policy](../retries/) to decide what to
  do.

We might rename `SocketOptions.setReadTimeoutMillis` in a future version to clear up any confusion.

[SocketOptions]:           http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html
[setReadTimeoutMillis]:    http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setReadTimeoutMillis-int-
[setConnectTimeoutMillis]: http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setConnectTimeoutMillis-int-
[setKeepAlive]:            http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setKeepAlive-boolean-
[setReceiveBufferSize]:    http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setReceiveBufferSize-int-
[setReuseAddress]:         http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setReuseAddress-boolean-
[setSendBufferSize]:       http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setSendBufferSize-int-
[setSoLinger]:             http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setSoLinger-int-
[setTcpNoDelay]:           http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/SocketOptions.html#setTcpNoDelay-boolean-
[onReadTimeout]:           http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/policies/RetryPolicy.html#onReadTimeout-com.datastax.driver.core.Statement-com.datastax.driver.core.ConsistencyLevel-int-int-boolean-int-