@devioarts/capacitor-tcpclient
v0.0.3
Published
TCP Client for Capacitor working on Android, iOS and Electron
Maintainers
Readme
@devioarts/capacitor-tcpclient
TCP Client for Capacitor with iOS/Android/Electron support - Example App
Install
npm install @devioarts/capacitor-tcpclient
npx cap syncAndroid
/android/app/src/main/AndroidManifest.xml
<application
android:usesCleartextTraffic="true"
></application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Android 12+ -->
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
iOS
/ios/App/App/Info.plist
<key>NSLocalNetworkUsageDescription</key>
<string>It is needed for the correct functioning of the application</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsLocalNetworking</key>
<true/>
</dict>ElectronJS
Implementation example was developed on capacitor-electron base, if you run electron differently, you may need to adjust the code.
/electron/main.ts
// ...
// THIS LINE IS IMPORTANT FOR PLUGIN!
import {TCPClient} from "@devioarts/capacitor-tcpclient/electron/tcpclient";
// ...
// THIS LINE IS IMPORTANT FOR PLUGIN!
let tcpClient: TCPClient | null = null;
// ...
function createWindow() {
const win = new BrowserWindow(
// ...
);
// ...
// THIS LINE IS IMPORTANT FOR PLUGIN!
tcpClient = new TCPClient(win);
// ...
}
// ...electron/preload.cjs
const { contextBridge, ipcRenderer } = require("electron");
// THIS LINE IS IMPORTANT FOR PLUGIN!
const {createTCPClientAPI} = require("@devioarts/capacitor-tcpclient/electron/tcpclient-bridge.cjs");
// ...
// THIS LINE IS IMPORTANT FOR PLUGIN!
contextBridge.exposeInMainWorld('TCPClient', createTCPClientAPI({ ipcRenderer }));
// ...API
connect(...)disconnect()isConnected()isReading()write(...)writeAndRead(...)startRead(...)stopRead()setReadTimeout(...)addListener('tcpData', ...)addListener('tcpDisconnect', ...)removeAllListeners()- Interfaces
- Type Aliases
connect(...)
connect(options: TcpConnectOptions) => Promise<TcpConnectResult>Open a TCP connection.
| Param | Type |
| ------------- | --------------------------------------------------------------- |
| options | TcpConnectOptions |
Returns: Promise<TcpConnectResult>
disconnect()
disconnect() => Promise<TcpDisconnectResult>Close the TCP connection. Idempotent. Triggers tcpDisconnect(manual).
Returns: Promise<TcpDisconnectResult>
isConnected()
isConnected() => Promise<TcpIsConnectedResult>Check whether the socket is connected.
Returns: Promise<TcpIsConnectedResult>
isReading()
isReading() => Promise<TcpIsReadingResult>Check whether the stream reader is active.
Returns: Promise<TcpIsReadingResult>
write(...)
write(options: TcpWriteOptions) => Promise<TcpWriteResult>Write raw bytes.
| Param | Type |
| ------------- | ----------------------------------------------------------- |
| options | TcpWriteOptions |
Returns: Promise<TcpWriteResult>
writeAndRead(...)
writeAndRead(options: TcpWriteAndReadOptions) => Promise<TcpWriteAndReadResult>Write request, then read reply under the given constraints.
| Param | Type |
| ------------- | ------------------------------------------------------------------------- |
| options | TcpWriteAndReadOptions |
Returns: Promise<TcpWriteAndReadResult>
startRead(...)
startRead(options?: TcpStartReadOptions | undefined) => Promise<TcpStartStopResult>Start emitting tcpData events. Safe to call multiple times.
| Param | Type |
| ------------- | ------------------------------------------------------------------- |
| options | TcpStartReadOptions |
Returns: Promise<TcpStartStopResult>
stopRead()
stopRead() => Promise<TcpStartStopResult>Stop emitting tcpData events. Safe to call multiple times.
Returns: Promise<TcpStartStopResult>
setReadTimeout(...)
setReadTimeout(options: { readTimeout: number; }) => Promise<{ error: boolean; errorMessage?: string | null; }>Configure stream read timeout (Android only). iOS: no-op; Electron: stored for RR defaults. Provided for API parity across platforms.
| Param | Type |
| ------------- | ------------------------------------- |
| options | { readTimeout: number; } |
Returns: Promise<{ error: boolean; errorMessage?: string | null; }>
addListener('tcpData', ...)
addListener(eventName: 'tcpData', listenerFunc: (event: TcpDataEvent) => void) => Promise<PluginListenerHandle>Subscribe to micro-batched stream data events.
| Param | Type |
| ------------------ | ------------------------------------------------------------------------- |
| eventName | 'tcpData' |
| listenerFunc | (event: TcpDataEvent) => void |
Returns: Promise<PluginListenerHandle>
addListener('tcpDisconnect', ...)
addListener(eventName: 'tcpDisconnect', listenerFunc: (event: TcpDisconnectEvent) => void) => Promise<PluginListenerHandle>Subscribe to disconnect notifications.
| Param | Type |
| ------------------ | ------------------------------------------------------------------------------------- |
| eventName | 'tcpDisconnect' |
| listenerFunc | (event: TcpDisconnectEvent) => void |
Returns: Promise<PluginListenerHandle>
removeAllListeners()
removeAllListeners() => Promise<void>Remove all tcpData/tcpDisconnect listeners.
Interfaces
TcpConnectResult
Result of connect().
- connected=true on success; false on failure.
- error=true with errorMessage on failure (e.g., "connect timeout", "connect failed: ...").
| Prop | Type |
| ------------------ | --------------------------- |
| error | boolean |
| errorMessage | string | null |
| connected | boolean |
TcpConnectOptions
Connection parameters for opening a TCP socket.
Notes by platform:
- Android: validates port range (1..65535); applies TCP_NODELAY and SO_KEEPALIVE according to the flags. Connect timeout is enforced by Socket#connect.
- iOS: sets TCP_NODELAY, SO_KEEPALIVE and SO_NOSIGPIPE. Connect timeout is enforced using non-blocking connect + polling.
- Electron: sets noDelay and keepAlive (with 60s initial delay). Connect timeout is emulated via a JS timer that destroys the socket if elapsed.
| Prop | Type | Description |
| --------------- | -------------------- | ------------------------------------------------------------------------ |
| host | string | Hostname or IP address to connect to. Required. |
| port | number | TCP port, defaults to 9100. Valid range 1..65535 (validated on Android). |
| timeout | number | Connect timeout in milliseconds, defaults to 3000. |
| noDelay | boolean | Enable TCP_NODELAY (Nagle off). Defaults to true. |
| keepAlive | boolean | Enable SO_KEEPALIVE. Defaults to true. |
TcpDisconnectResult
Result of disconnect(). Always resolves. After disconnect, reading is false. A tcpDisconnect event with reason 'manual' is also emitted by platforms.
| Prop | Type | Description |
| ------------------ | --------------------------- | -------------------------------------------------------------------- |
| error | boolean | |
| errorMessage | string | null | |
| disconnected | boolean | True if the instance transitioned to disconnected state. |
| reading | boolean | Whether the stream reader is active (always false after disconnect). |
TcpIsConnectedResult
Result of isConnected().
- Android performs a safe 1-byte peek unless streaming/RR is active, in which case it returns true if those are active to avoid consuming input.
- iOS/Electron return based on current socket open/close state.
| Prop | Type |
| ------------------ | --------------------------- |
| error | boolean |
| errorMessage | string | null |
| connected | boolean |
TcpIsReadingResult
Result of isReading(). True if stream reader is active.
| Prop | Type |
| ------------------ | --------------------------- |
| error | boolean |
| errorMessage | string | null |
| reading | boolean |
TcpWriteResult
Result of write().
- bytesSent equals the request length on success; 0 on failure.
- Fails with error=true if not connected or busy (RR in progress on some platforms).
| Prop | Type |
| ------------------ | --------------------------- |
| error | boolean |
| errorMessage | string | null |
| bytesSent | number |
TcpWriteOptions
Bytes to write to the socket verbatim. Accepts number[] or Uint8Array.
| Prop | Type |
| ---------- | ------------------------------------------------------------- |
| data | number[] | Uint8Array |
Uint8Array
A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the requested number of bytes could not be allocated an exception is raised.
| Prop | Type | Description |
| ----------------------- | ----------------------------------------------------------- | ---------------------------------------------------------------------------- |
| BYTES_PER_ELEMENT | number | The size in bytes of each element in the array. |
| buffer | ArrayBufferLike | The ArrayBuffer instance referenced by the array. |
| byteLength | number | The length in bytes of the array. |
| byteOffset | number | The offset in bytes of the array. |
| length | number | The length of the array. |
| Method | Signature | Description | | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | copyWithin | (target: number, start: number, end?: number | undefined) => this | Returns the this object after copying a section of the array identified by start and end to the same array starting at position target | | every | (predicate: (value: number, index: number, array: Uint8Array) => unknown, thisArg?: any) => boolean | Determines whether all the members of an array satisfy the specified test. | | fill | (value: number, start?: number | undefined, end?: number | undefined) => this | Returns the this object after filling the section identified by start and end with value | | filter | (predicate: (value: number, index: number, array: Uint8Array) => any, thisArg?: any) => Uint8Array | Returns the elements of an array that meet the condition specified in a callback function. | | find | (predicate: (value: number, index: number, obj: Uint8Array) => boolean, thisArg?: any) => number | undefined | Returns the value of the first element in the array where predicate is true, and undefined otherwise. | | findIndex | (predicate: (value: number, index: number, obj: Uint8Array) => boolean, thisArg?: any) => number | Returns the index of the first element in the array where predicate is true, and -1 otherwise. | | forEach | (callbackfn: (value: number, index: number, array: Uint8Array) => void, thisArg?: any) => void | Performs the specified action for each element in an array. | | indexOf | (searchElement: number, fromIndex?: number | undefined) => number | Returns the index of the first occurrence of a value in an array. | | join | (separator?: string | undefined) => string | Adds all the elements of an array separated by the specified separator string. | | lastIndexOf | (searchElement: number, fromIndex?: number | undefined) => number | Returns the index of the last occurrence of a value in an array. | | map | (callbackfn: (value: number, index: number, array: Uint8Array) => number, thisArg?: any) => Uint8Array | Calls a defined callback function on each element of an array, and returns an array that contains the results. | | reduce | (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number) => number | Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. | | reduce | (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, initialValue: number) => number | | | reduce | <U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U, initialValue: U) => U | Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. | | reduceRight | (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number) => number | Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. | | reduceRight | (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, initialValue: number) => number | | | reduceRight | <U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U, initialValue: U) => U | Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. | | reverse | () => Uint8Array | Reverses the elements in an Array. | | set | (array: ArrayLike<number>, offset?: number | undefined) => void | Sets a value or an array of values. | | slice | (start?: number | undefined, end?: number | undefined) => Uint8Array | Returns a section of an array. | | some | (predicate: (value: number, index: number, array: Uint8Array) => unknown, thisArg?: any) => boolean | Determines whether the specified callback function returns true for any element of an array. | | sort | (compareFn?: ((a: number, b: number) => number) | undefined) => this | Sorts an array. | | subarray | (begin?: number | undefined, end?: number | undefined) => Uint8Array | Gets a new Uint8Array view of the ArrayBuffer store for this array, referencing the elements at begin, inclusive, up to end, exclusive. | | toLocaleString | () => string | Converts a number to a string by using the current locale. | | toString | () => string | Returns a string representation of an array. | | valueOf | () => Uint8Array | Returns the primitive value of the specified object. |
ArrayLike
| Prop | Type |
| ------------ | ------------------- |
| length | number |
ArrayBufferTypes
Allowed ArrayBuffer types for the buffer of an ArrayBufferView and related Typed Arrays.
| Prop | Type |
| ----------------- | --------------------------------------------------- |
| ArrayBuffer | ArrayBuffer |
ArrayBuffer
Represents a raw buffer of binary data, which is used to store data for the different typed arrays. ArrayBuffers cannot be read from or written to directly, but can be passed to a typed array or DataView Object to interpret the raw buffer as needed.
| Prop | Type | Description |
| ---------------- | ------------------- | ------------------------------------------------------------------------------- |
| byteLength | number | Read-only. The length of the ArrayBuffer (in bytes). |
| Method | Signature | Description | | --------- | --------------------------------------------------------------------------------------- | --------------------------------------------------------------- | | slice | (begin: number, end?: number | undefined) => ArrayBuffer | Returns a section of an ArrayBuffer. |
TcpWriteAndReadResult
Result of writeAndRead().
- bytesSent is the number of request bytes written. If the operation fails due to a pure timeout (no bytes received), bytesSent can still equal the request length; for other errors it is 0.
- bytesReceived is the length of returned data (<= maxBytes).
- matched indicates whether the expect pattern (if any) was found.
| Prop | Type | Description |
| ------------------- | --------------------------- | ----------------------------------------------------------- |
| error | boolean | |
| errorMessage | string | null | |
| bytesSent | number | |
| bytesReceived | number | |
| data | number[] | Received bytes (may be partial if timeout after some data). |
| matched | boolean | True if the expect pattern was matched; false otherwise. |
TcpWriteAndReadOptions
Options for writeAndRead() request/response operation.
Behavior summary (parity across Android/iOS/Electron):
- The request is written atomically with internal serialization (no interleaved writes across concurrent calls).
- Response collection ends when ANY of these happens: • expect pattern is found (matched=true), or • maxBytes cap is reached, or • without expect: adaptive "until-idle" period elapses after last data, or • absolute timeout elapses (see errors below).
- On timeout: • If no data arrived at all, the call fails with error=true and errorMessage resembling "connect timeout" and bytesSent equals the request length on Android/iOS/Electron; bytesReceived=0, matched=false. • If some data arrived before the deadline, the call resolves successfully with matched=false and returns the partial data.
- suspendStreamDuringRR: when true, the active stream reader is temporarily stopped for the RR window to avoid racing over the same bytes; after RR it is resumed with the previous chunk size. Default is true on Android & iOS; Electron treats it as true by default as well.
- expect: hex string like "0A0B0C" (case/spacing ignored) or a byte array.
| Prop | Type | Description |
| --------------------------- | ----------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| data | number[] | Uint8Array | Request payload to send. |
| timeout | number | Absolute RR timeout in ms. Defaults to 1000. |
| maxBytes | number | Maximum number of bytes to accumulate and return. Defaults to 4096. |
| expect | string | number[] | Uint8Array | Optional expected pattern. When provided, reading stops as soon as the accumulated buffer contains this pattern. Accepts: - number[] / Uint8Array: raw byte sequence - string: hex bytes (e.g., "0x1b40", "1B 40"), spacing and case ignored |
| suspendStreamDuringRR | boolean | Temporarily suspend the stream reader during RR to avoid consuming reply in the stream. Defaults to true (Android default true; iOS behaves as if true; Electron defaults to true as well). |
TcpStartStopResult
Result of startRead()/stopRead().
| Prop | Type | Description |
| ------------------ | --------------------------- | ---------------------------------------------- |
| error | boolean | |
| errorMessage | string | null | |
| reading | boolean | Whether the stream reader is currently active. |
TcpStartReadOptions
Options for startRead().
- chunkSize controls maximum size of a single tcpData event slice. Native implementations may micro-batch multiple small reads; Electron additionally splits a flushed batch into slices up to chunkSize to preserve consumer expectations.
- readTimeout applies only on Android (socket SO_TIMEOUT while streaming). It is a no-op on iOS. Electron stores it for RR but does not apply to stream.
| Prop | Type | Description |
| ----------------- | ------------------- | ------------------------------------------------------------------ |
| chunkSize | number | Maximum bytes per emitted tcpData event. Default 4096. |
| readTimeout | number | Stream read timeout (ms). Android: applies SO_TIMEOUT; iOS: no-op. |
PluginListenerHandle
| Prop | Type |
| ------------ | ----------------------------------------- |
| remove | () => Promise<void> |
TcpDataEvent
Emitted by the stream reader with micro-batched data chunks.
- Data values are 0..255. The plugin may coalesce multiple small reads and then emit one or more events capped by chunkSize.
| Prop | Type |
| ---------- | --------------------- |
| data | number[] |
TcpDisconnectEvent
Emitted when the socket is closed or the plugin disconnects it.
- reason: • 'manual' — disconnect() called or instance disposed. • 'remote' — the peer closed the connection (EOF). • 'error' — an I/O error occurred; error contains a message.
- reading is false when this event fires.
| Prop | Type |
| ------------------ | -------------------------------------------- |
| disconnected | true |
| reading | boolean |
| reason | 'error' | 'manual' | 'remote' |
| error | string |
Type Aliases
ArrayBufferLike
ArrayBufferTypes[keyof ArrayBufferTypes]
