---
id: network--tcp-client-plugin
title: "Tcp client"
summary: "Opens a persistent TCP connection to a remote server, writes the bytes of every input record to it and, optionally, emits everything the server sends back. Use it to talk to devices or services with a raw TCP protocol."
audience: user
keywords: "input, output, continue, address, port, connecttimeout, writetimeout, readtimeout"
---
# Tcp client

Opens a persistent TCP connection to a remote server, writes the bytes of every input record to it and, optionally, emits everything the server sends back. Use it to talk to devices or services with a raw TCP protocol.

## Pins

| Pin | Kind | Types | Description |
|---|---|---|---|
| Input | input | `Viaducta.Plugins.UdpTypes.TcpDatagram`, `Viaducta.Plugins.UdpTypes.UdpDatagram`, `Viaducta.Plugins.TextPlugin.Types.TextRecord` | Data to send. |
| Output | output | `Viaducta.Plugins.UdpTypes.TcpDatagram` | Data received from the server, with new metadata. Only active when connected. |
| Continue | continue | same as input | Called after the data was written, with the original input and metadata. |

## Configuration

| Field | Type | Default | Description |
|---|---|---|---|
| `Address` | string | `127.0.0.1` | Required. Host name or IP of the TCP server. |
| `Port` | integer (1-65535) | `7100` | Required. Server port. |
| `ConnectTimeOut` | integer (seconds) | `10` | How long to wait for the connection to be established. |
| `WriteTimeOut` | integer (seconds) | `5` | Write timeout on the socket. `0` = no timeout. |
| `ReadTimeOut` | integer (seconds) | `0` | Intended read timeout, `0` = wait indefinitely (see Notes). |

## Behaviour

- The connection is opened on the first input record and kept open for later records (one connection per component).
- What is sent:
  - `TcpDatagram` / `UdpDatagram`: the `Data` bytes (`IP`, `Port` and `SessionId` are ignored; the target is always `Address`:`Port`).
  - `TextRecord`: `Value` encoded as UTF-8.
  - Empty data or another type throws an exception.
- Bytes are written as they are; no delimiter, length prefix or other framing is added.
- If `Output` has connections, a background reader is started with the connection. Each read (up to 32 KB) is emitted as one `TcpDatagram` with `IP` = `Address`, `Port` = `Port`, `Data` = received bytes and new metadata. There is no message framing: one server message can arrive split over several datagrams, or several messages in one.
- When the reader detects a lost connection and `Output` is connected, the next input record reconnects.
- On start the flow fails if `Address` is empty or `Port` is out of range.

## Notes

- If `Output` has no connections, a broken connection is not re-established: later writes keep failing until the flow is restarted.
- A connect timeout is not detected as such: the subsequent write fails with a "not connected" error. A refused connection throws an exception for the record.
- `ReadTimeOut` has no effect, because the reader uses asynchronous reads that ignore the socket read timeout.
- Responses are not correlated with requests; if you need request/response pairing, frame and match the messages downstream.
- The error for an unsupported input type mentions "UDP"; it refers to this component.

## Example

```json
{ "Address": "10.0.0.20", "Port": 7100, "ConnectTimeOut": 10, "WriteTimeOut": 5 }
```

Data mapper (build `TextRecord` command) → **Tcp client** → `Output` → (parse device reply) → ...
