:sourcedir: {core}/src/main/java
:examples-link: {reactor-netty-github-repo}/reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/tcp/server
:examples-dir: {examples}/src/main/java/reactor/netty/examples/documentation/tcp/server
:wirelogger: reactor.netty.tcp.TcpServer

[[tcp-server]]
= TCP Server

`Reactor Netty` provides an easy to use and configure
{javadoc}/reactor/netty/tcp/TcpServer.html[`TcpServer`].
It hides most of the `Netty` functionality that is needed to create a `TCP` server
and adds `Reactive Streams` backpressure.

[[starting-and-stopping]]
== Starting and Stopping

To start a `TCP` server, you must create and configure a
{javadoc}/reactor/netty/tcp/TcpServer.html[`TcpServer`] instance.
By default, the `host` is configured for any local address, and the system picks up an ephemeral port
when the `bind` operation is invoked. The following example shows how to create and
configure a `TcpServer` instance:

{examples-link}/create/Application.java
[%unbreakable]
----
include::{examples-dir}/create/Application.java[lines=18..31]
----
<1> Creates a {javadoc}/reactor/netty/tcp/TcpServer.html[`TcpServer`]
instance that is ready for configuring.
<2> Starts the server in a blocking fashion and waits for it to finish initializing.

The returned {javadoc}/reactor/netty/DisposableServer.html[`DisposableServer`]
offers a simple server API, including {javadoc}/reactor/netty/DisposableChannel.html#disposeNow-java.time.Duration-[`disposeNow()`],
which shuts the server down in a blocking fashion.

[[host-and-port]]
=== Host and Port

To serve on a specific `host` and `port`, you can apply the following configuration to the `TCP` server:

{examples-link}/address/Application.java
[%unbreakable]
----
include::{examples-dir}/address/Application.java[lines=18..33]
----
<1> Configures the `TCP` server host
<2> Configures the `TCP` server port

To serve on multiple addresses, after having configured the `TcpServer` you can bind it multiple times to obtain separate `DisposableServer`s.
All created servers will share resources such as `LoopResources` because they use the same configuration instance under the hood.

{examples-link}/address/MultiAddressApplication.java
[%unbreakable]
----
include::{examples-dir}/address/MultiAddressApplication.java[lines=18..41]
----
<1> Configures the first `TCP` server host
<2> Configures the first `TCP` server port
<3> Configures the second `TCP` server host
<4> Configures the second `TCP` server port

[[eager-initialization]]
== Eager Initialization

By default, the initialization of the `TcpServer` resources happens on demand. This means that the `bind
operation` absorbs the extra time needed to initialize and load:

 * the event loop groups
 * the native transport libraries (when native transport is used)
 * the native libraries for the security (in case of `OpenSsl`)

When you need to preload these resources, you can configure the `TcpServer` as follows:

{examples-link}/warmup/Application.java
[%unbreakable]
----
include::{examples-dir}/warmup/Application.java[lines=18..36]
----
<1> Initialize and load the event loop groups, the native transport libraries and the native libraries for the security

[[writing-data]]
== Writing Data

In order to send data to a connected client, you must attach an I/O handler.
The I/O handler has access to {javadoc}/reactor/netty/NettyOutbound.html[`NettyOutbound`]
to be able to write data. The following example shows how to attach an I/O handler:

{examples-link}/send/Application.java
[%unbreakable]
----
include::{examples-dir}/send/Application.java[lines=18..33]
----
<1> Sends `hello` string to the connected clients

[[consuming-data]]
== Consuming Data

In order to receive data from a connected client, you must attach an I/O handler.
The I/O handler has access to {javadoc}/reactor/netty/NettyInbound.html[`NettyInbound`]
to be able to read data. The following example shows how to use it:

{examples-link}/read/Application.java
[%unbreakable]
----
include::{examples-dir}/read/Application.java[lines=18..32]
----
<1> Receives data from the connected clients

[[lifecycle-callbacks]]
== Lifecycle Callbacks

The following lifecycle callbacks are provided to let you extend the `TcpServer`:

[width="100%",options="header"]
|=======
| Callback | Description
| `doOnBind` | Invoked when the server channel is about to bind.
| `doOnBound` | Invoked when the server channel is bound.
| `doOnChannelInit` | Invoked when initializing the channel.
| `doOnConnection` | Invoked when a remote client is connected
| `doOnUnbound` | Invoked when the server channel is unbound.
|=======

The following example uses the `doOnConnection` and `doOnChannelInit` callbacks:

{examples-link}/lifecycle/Application.java
[%unbreakable]
----
include::{examples-dir}/lifecycle/Application.java[lines=18..39]
----
<1> `Netty` pipeline is extended with `ReadTimeoutHandler` when a remote client is connected.
<2> `Netty` pipeline is extended with `LoggingHandler` when initializing the channel.

[[tcp-level-configurations]]
== TCP-level Configurations

This section describes three kinds of configuration that you can use at the TCP level:

* xref:tcp-server.adoc#server-tcp-level-configurations-channel-options[Setting Channel Options]
* xref:tcp-server.adoc#server-tcp-level-configurations-event-wire-logger[Wire Logger]
* xref:tcp-server.adoc#server-tcp-level-configurations-event-loop-group[Event Loop Group]

[[server-tcp-level-configurations-channel-options]]
=== Setting Channel Options

By default, the `TCP` server is configured with the following options:

{core-source-link}/reactor/netty/tcp/TcpServerBind.java
[%unbreakable]
----
include::{sourcedir}/reactor/netty/tcp/TcpServerBind.java[lines=38..46]
----

If additional options are necessary or changes to the current options are needed, you can apply the following configuration:

{examples-link}/channeloptions/Application.java
[%unbreakable]
----
include::{examples-dir}/channeloptions/Application.java[lines=18..33]
----

You can find more about `Netty` channel options at the following links:

* {nettyjavadoc}/io/netty/channel/ChannelOption.html[Common ChannelOption]
* {nettyjavadoc}/io/netty/channel/epoll/EpollChannelOption.html[Epoll ChannelOption]
* {nettyjavadoc}/io/netty/channel/kqueue/KQueueChannelOption.html[KQueue ChannelOption]
* https://docs.oracle.com/javase/8/docs/technotes/guides/net/socketOpt.html[Socket Options]

[[server-tcp-level-configurations-event-wire-logger]]
include::partial$wire-logger.adoc[]

[[server-tcp-level-configurations-event-loop-group]]
include::partial$eventloop.adoc[]

[[ssl-and-tls]]
== SSL and TLS

When you need SSL or TLS, you can apply the configuration shown in the next listing.
By default, if `OpenSSL` is available,
{nettyjavadoc}/io/netty/handler/ssl/SslProvider.html#OPENSSL[`SslProvider.OPENSSL`]
provider is used as a provider. Otherwise
{nettyjavadoc}/io/netty/handler/ssl/SslProvider.html#JDK[`SslProvider.JDK`] is used.
Switching the provider can be done through
{nettyjavadoc}/io/netty/handler/ssl/SslContextBuilder.html#sslProvider-io.netty.handler.ssl.SslProvider-[`SslContextBuilder`]
or by setting `-Dio.netty.handler.ssl.noOpenSsl=true`.

The following example uses `SslContextBuilder`:

{examples-link}/security/Application.java
[%unbreakable]
----
include::{examples-dir}/security/Application.java[lines=18..40]
----

[[server-name-indication]]
=== Server Name Indication
You can configure the `TCP` server with multiple `SslContext` mapped to a specific domain.
An exact domain name or a domain name containing a wildcard can be used when configuring the `SNI` mapping.

The following example uses a domain name containing a wildcard:

{examples-link}/sni/Application.java
[%unbreakable]
----
include::{examples-dir}/sni/Application.java[lines=18..47]
----

[[metrics]]
== Metrics
The TCP server supports built-in integration with https://micrometer.io/[`Micrometer`].
It exposes all metrics with a prefix of `reactor.netty.tcp.server`.

The following table provides information for the TCP server metrics:

[width="100%",options="header"]
|=======
| metric name | type | description
| reactor.netty.tcp.server.connections.total | Gauge | The number of all opened connections.
See xref:observability.adoc#observability-metrics-connections-total[Connections Total]
| reactor.netty.tcp.server.data.received | DistributionSummary | Amount of the data received, in bytes.
See xref:observability.adoc#observability-metrics-data-received[Data Received]
| reactor.netty.tcp.server.data.sent | DistributionSummary | Amount of the data sent, in bytes.
See xref:observability.adoc#observability-metrics-data-sent[Data Sent]
| reactor.netty.tcp.server.errors | Counter | Number of errors that occurred.
See xref:observability.adoc#observability-metrics-errors-count[Errors Count]
| reactor.netty.tcp.server.tls.handshake.time | Timer | Time spent for TLS handshake.
See xref:observability.adoc#observability-metrics-tls-handshake-time[Tls Handshake Time]
|=======

These additional metrics are also available:

include::partial$alloc-metrics.adoc[]
include::partial$eventloop-metrics.adoc[]

The following example enables that integration:

{examples-link}/metrics/Application.java
[%unbreakable]
----
include::{examples-dir}/metrics/Application.java[lines=18..32]
----
<1> Enables the built-in integration with Micrometer

When TCP server metrics are needed for an integration with a system other than `Micrometer` or you want
to provide your own integration with `Micrometer`, you can provide your own metrics recorder, as follows:

{examples-link}/metrics/custom/Application.java
[%unbreakable]
----
include::{examples-dir}/metrics/custom/Application.java[lines=18..35]
----
<1> Enables TCP server metrics and provides {javadoc}/reactor/netty/channel/ChannelMetricsRecorder.html[`ChannelMetricsRecorder`] implementation.

[[tracing]]
== Tracing
The TCP server supports built-in integration with https://micrometer.io/docs/tracing[`Micrometer Tracing`].

The following table provides information for the TCP server spans:

[width="100%",options="header"]
|=======
| contextual name | description
| tls handshake | Information and time spent for TLS handshake.
See xref:observability.adoc#observability-spans-tls-handshake-span[Tls Handshake Span].
|=======

The following example enables that integration. This concrete example uses `Brave` and reports the information to `Zipkin`.
See the https://micrometer.io/docs/tracing#_micrometer_tracing_opentelemetry_setup[`Micrometer Tracing`] documentation for `OpenTelemetry` setup.

{examples-link}/tracing/Application.java
[%unbreakable]
----
include::{examples-dir}/tracing/Application.java[lines=18..81]
----
<1> Initializes Brave, Zipkin, and the Observation registry.
<2> Enables the built-in integration with Micrometer.

The result in `Zipkin` looks like:

image::tcp-server-tracing.png[role="invert-dark"]

[[access-current-observation]]
=== Access Current Observation
Project Micrometer provides https://micrometer.io/docs/contextPropagation[`a library`] that assists with context propagation across
different types of context mechanisms such as `ThreadLocal`, `Reactor Context` and others.

The following example shows how to use this library in a custom `ChannelHandler`:

{examples-link}/tracing/custom/Application.java
[%unbreakable]
----
include::{examples-dir}/tracing/custom/Application.java[lines=18..86]
----
<1> Initializes Brave, Zipkin, and the Observation registry.
<2> Enables the built-in integration with Micrometer.
<3> Custom `ChannelHandler` that uses context propagation library. This concrete example overrides only
`ChannelInboundHandlerAdapter#channelActive`, if it is needed, the same logic can be used for the rest of the methods.
Also, this concrete example sets all `ThreadLocal` values for which there is a value in the given `Channel`,
if another behaviour is needed please check https://micrometer.io/docs/contextPropagation[`context propagation library API`].
For example, you may want to set only some of the `ThreadLocal` values.

NOTE: When you enable Reactor Netty tracing within a framework, you may need to let Reactor Netty use the `ObservationRegistry` created by this framework.
For this purpose you need to invoke {javadoc}/reactor/netty/Metrics.html#observationRegistry-io.micrometer.observation.ObservationRegistry-[`reactor.netty.Metrics#observationRegistry`].
You may also need to configure the Reactor Netty `ObservationHandlers` using the API provided by the framework.

[[unix-domain-sockets]]
== Unix Domain Sockets
The `TCP` server supports Unix Domain Sockets (UDS) when native transport is in use for all java versions
and when NIO transport is in use for java 17 and above.

The following example shows how to use UDS support:

{examples-link}/uds/Application.java
[%unbreakable]
----
include::{examples-dir}/uds/Application.java[lines=18..38]
----
<1> Specifies `DomainSocketAddress` that will be used
