socketio

This project is developed based on socket.io-client-cpp.

Overview

socketio is a communication library for OpenHarmony that enables low-latency, bidirectional, event-based messaging between clients and servers. Built on the WebSocket protocol, it provides additional guarantees such as automatic fallback to HTTP long polling and automatic reconnection on disconnect.

Notes

  • socketio only supports HTTP-based connections and does not support HTTPS (TLS) protocol.
  • If you need to establish an encrypted connection via HTTPS (TLS), use the socketio_tls version instead.
  • The two versions are designed for HTTP and HTTPS scenarios respectively and cannot be mixed.
  • Compatible server versions: Socket.IO 3.x / 4.x

Display Effects

Login page

Chat page

How to Install

ohpm install @ohos/socketio

For more details on OpenHarmony ohpm environment configuration, see Installing an OpenHarmony HAR.

Constraints

Compatibility

Verified in the following versions:

  • DevEco Studio: 4.1.3.532, SDK: API11 (4.1.0.67 SP3);
  • DevEco Studio: Next Developer Beta1 (5.0.3.121), SDK: API12 (5.0.0.16);
  • DevEco Studio: NEXT Developer Beta2 (5.0.3.500), SDK: API12 (5.0.0.31);
  • DevEco Studio: NEXT Developer Beta1 (5.0.3.810), SDK: API12 (5.0.0.68);
  • DevEco Studio: 5.0.1 Release (5.0.5.310), SDK: API13 (5.0.1.115);

Permissions

To use network communication, declare the following permission in module.json5:

"requestPermissions": [
  {
    "name": "ohos.permission.INTERNET",
    "usedScene": {
      "abilities": ["EntryAbility"],
      "when": "always"
    }
  }
]

Usage Example

import { client_socket } from '@ohos/socketio';

// 1. Initialize the client
const client: client_socket = new client_socket();

// 2. Register connection state callbacks
client.set_open_listener(() => {
  console.info('Connected to server');
});
client.set_fail_listener(() => {
  console.error('Failed to connect to server');
});
client.set_close_listener((reason: string) => {
  console.info('Connection closed, reason: ' + reason);
});

// 3. Listen for server-pushed message events
client.on('new message', (event_json: string) => {
  const data:ESObject = JSON.parse(event_json);
  console.info('Received message: ' + JSON.stringify(data));
});

// 4. Connect to the server
client.connect('http://your-server-address:3000');

// 5. Send messages after the connection is established (call inside set_open_listener callback)
client.emit('add user', 'myUsername');
client.emit('new message', 'Hello, World!');

// 6. Close the connection when done
client.close();

How to Use

1. Initialization and Connection

import { client_socket } from '@ohos/socketio';

const client: client_socket = new client_socket();

// Register connection state listeners before calling connect
client.set_open_listener(() => { /* connected */ });
client.set_fail_listener(() => { /* connection failed */ });
client.set_reconnecting_listener(() => { /* reconnecting */ });
client.set_reconnect_listener(() => { /* reconnected */ });
client.set_close_listener((reason: string) => { /* disconnected */ });
client.set_socket_open_listener((nsp: string) => { /* namespace connected */ });
client.set_socket_close_listener((nsp: string) => { /* namespace disconnected */ });

// Connect to server
client.connect('http://your-server-address:3000');

2. Emitting Events

The emit method supports multiple data types: string, number, boolean, null, array, object, and Uint8Array. The last function argument is treated as a server ACK callback.

// Send a string message
client.emit('new message', 'Hello');

// Send an object
client.emit('login', { username: 'Alice' });

// Send multiple arguments
client.emit('update', 'status', 42, true);

// Receive a server ACK callback
client.emit('new message', 'Hello', (response: ESObject) => {
  console.info('Server acknowledged: ' + JSON.stringify(response));
});

// Send binary data with ACK
import { buffer_util } from '@ohos/socketio';
const bytes: Uint8Array = buffer_util.stringToUint8Array('binary content');
client.emitAckBinary('upload', bytes, (code: number, data: Uint8Array) => {
  console.info('Binary ACK, code=' + code + ', size=' + data.byteLength);
});

3. Listening for Events

// Listen for single-argument events (server emits a single JSON argument)
client.on('new message', (event_json: string) => {
  const data:ESObject = JSON.parse(event_json);
  console.info('Message: ' + data.message);
});

// Listen for multi-argument events (server emits multiple arguments)
client.on_multi('multi event', (...args: ESObject[]) => {
  console.info('Multi-arg event: ' + JSON.stringify(args));
});

// Listen for binary events
client.on_binary('file data', (data: Uint8Array) => {
  console.info('Received binary data, size: ' + data.byteLength + ' bytes');
});

// Listen only once
client.once('welcome', (data: string) => {
  console.info('Welcome message: ' + data);
});

// Built-in event: disconnection
client.on('disconnect', (data: string) => {
  console.info('Disconnected: ' + data);
});

// Built-in event: heartbeat
client.on('ping_pong', (data: string) => {
  console.info('Heartbeat: ' + data);
});

// Remove a specific event listener
client.off('new message');

// Remove all event listeners
client.off_all();

4. Reconnection Configuration

Option 1: Use individual methods

client.set_reconnect_attempts(5);      // Maximum 5 reconnect attempts
client.set_reconnect_delay(1000);      // Initial reconnect delay: 1000 ms
client.set_reconnect_delay_max(5000);  // Maximum reconnect delay: 5000 ms

5. Custom Headers and Namespaces

// Set custom HTTP headers for the handshake (e.g., token authentication), must be called before connect
client.set_headers('Authorization: Bearer your_token_here');

// Set namespace, must be called before connect
client.set_nsp('/chat');

client.connect('http://your-server:3000');

6. Proxy Authentication

// Set HTTP proxy Basic authentication, must be called before connect
client.set_proxy_basic_auth('http://proxy-server:8080', 'username', 'password');

7. Log Level

client.set_logs_quiet();    // Disable logging
client.set_logs_default();  // Default log level
client.set_logs_verbose();  // Verbose logging (for debugging)

8. Closing the Connection

// Asynchronous close (recommended)
client.close();

// Synchronous close (blocks the current thread until fully released, use with caution)
client.sync_close();

Always call close() when the application goes to the background or the page is destroyed, to release connection resources and prevent memory leaks.

9. Binary Data Utilities

buffer_util provides conversion between strings and Uint8Array:

import { buffer_util } from '@ohos/socketio';

// Convert string to Uint8Array
const bytes: Uint8Array = buffer_util.stringToUint8Array('hello world');

// Convert Uint8Array to string
const str: string = buffer_util.uint8ArrayToString(bytes);

Available APIs

client_socket

Connection Management

Name Description Parameters Return
constructor() Initializes the client instance - -
connect(uri) Connects to the server at the specified URI uri: string void
close() Asynchronously closes the connection - void
sync_close() Synchronously closes the connection, blocking until fully released - void
opened() Returns whether the connection is currently established - boolean
get_current_state() Returns the current connection state: 0 not connected, 1 disconnecting, 2 connecting, 3 connected - number
get_sessionid() Returns the current session ID - string
set_option(opt) Sets URL query (must be called before connect) opt: string void

set_option Fields

Field Type Required Default Description
reconnection boolean No true Whether to enable automatic reconnection
reconnectionAttempts number No unlimited Maximum number of reconnection attempts
reconnectionDelay number No 1000 Initial reconnection delay in milliseconds
reconnectionDelayMax number No 5000 Maximum reconnection delay in milliseconds

Connection State Listeners

Name Description Parameters Return
set_open_listener(on_open) Registers a callback for connection success on_open: () => void void
set_fail_listener(on_fail) Registers a callback for connection failure on_fail: () => void void
set_reconnecting_listener(fn) Registers a callback for reconnecting state fn: () => void void
set_reconnect_listener(fn) Registers a callback for reconnection success fn: () => void void
set_close_listener(on_close) Registers a callback for disconnection; the callback receives the disconnect reason on_close: (reason: string) => void void
set_socket_open_listener(fn) Registers a callback for socket namespace connection success fn: (nsp: string) => void void
set_socket_close_listener(fn) Registers a callback for socket namespace disconnection fn: (nsp: string) => void void
clear_con_listeners() Clears all connection state listeners - void

Event Sending and Receiving

Name Description Parameters Return
on(event_name, listener) Registers an event listener; callback receives a single JSON string event_name: string; listener: (event_json: string) => void void
on_multi(event_name, listener) Registers a multi-argument event listener; use when the server emits multiple arguments event_name: string; listener: (...args: ESObject[]) => void void
on_binary(event_name, listener) Registers a binary event listener; callback receives Uint8Array event_name: string; listener: (data: Uint8Array) => void void
once(event_name, listener) Registers an event listener that fires only once event_name: string; listener: (event_json: string) => void void
off(event_name) Removes the listener for the specified event event_name: string void
off_all() Removes all event listeners - void
clear_socket_listeners() Clears all socket-level listeners - void
socket_close() Closes the current socket namespace connection - void
on_error(listener) Registers an error event listener listener: (message: string) => void void
off_error() Removes the error event listener - void
emit(name, ...args) Sends an event to the server; supports multiple data types; the last function argument is used as a server ACK callback name: string; ...args: Array<string | number | boolean | null | object | ArrayBuffer | Array<...> | Function> void
emitAckBinary(name, message, callback?) Sends a binary data event and waits for server ACK name: string; message: ESObject; callback?: (code: number, data: Uint8Array) => void void

Built-in Events

Event Name Trigger Callback Parameter
disconnect Triggered when the client disconnects data: string disconnect reason
ping_pong Triggered during heartbeat detection between client and server data: string heartbeat data

Reconnection Configuration

Name Description Parameters Return
set_reconnect_attempts(attempts) Sets the maximum number of reconnection attempts attempts: number void
set_reconnect_delay(millis) Sets the initial reconnection delay in milliseconds millis: number void
set_reconnect_delay_max(millis) Sets the maximum reconnection delay in milliseconds millis: number void

Other Configuration

Name Description Parameters Return
set_headers(headers) Sets custom HTTP headers for the handshake headers: string void
set_nsp(nsp) Sets the connection namespace (must be called before connect) nsp: string void
set_proxy_basic_auth(uri, username, password) Sets HTTP proxy Basic authentication credentials uri: string; username: string; password: string void
set_logs_default() Sets the default log level - void
set_logs_quiet() Disables log output - void
set_logs_verbose() Enables verbose logging (for debugging) - void

buffer_util

A utility class for converting between strings and binary data.

Name Description Parameters Return
uint8ArrayToString(uint8Array) Converts a Uint8Array to a string uint8Array: Uint8Array string
stringToUint8Array(message_string) Converts a string to a Uint8Array message_string: string Uint8Array

Source Code Download

  1. This project depends on the socket.io-client-cpp library via git submodule. Add the --recursive flag when cloning:

    git clone --recursive https://gitcode.com/openharmony-tpc/openharmony_tpc_samples.git
    
  2. Windows only: After cloning, navigate to socketio/library/src/main/cpp/thirdModule and run the modify.sh script to apply the patch files to the socket.io-client-cpp source. This step is not required on Linux.

  3. After completing the above steps, you can build the project.

About Obfuscation

For information on code obfuscation, see Code Obfuscation.

To prevent the socketio library from being obfuscated, add the following exclusion rule to obfuscation-rules.txt:

-keep
./oh_modules/@ohos/socketio

Directory Structure

|---- socketio
|     |---- entry                              # Sample code
|     |---- library                            # socketio library
|           |---- index.ets                    # Export entry
|           |---- src/main/ets                 # ArkTS API layer
|                 |---- client_socket.ets      # Core client API
|                 |---- buffer_util.ets        # Binary data utility
|           |---- src/main/cpp                 # C++ native layer
|                 |---- client_socket.h        # C++ API declarations
|                 |---- native-bridge.cpp      # NAPI bridge
|                 |---- socket.io-client-cpp   # socket.io C++ client library (git submodule)
|     |---- README.md                          # English documentation
|     |---- README_zh.md                       # Chinese documentation

How to Contribute

If you find any issue when using socketio, submit an Issue or a PR.

License

This project is licensed under MIT License.