WebsocketClient Node
The WebsocketClient
node provides a higher-level interface for interacting with WebSocket servers, building upon Godot's built-in WebSocketPeer
. Its main enhancement is the addition of automatic reconnection logic with exponential backoff.
Overview
This node wraps a WebSocketPeer
instance and manages its connection lifecycle. Key features include:
- Connection Management: Handles connecting to a specified
connection_url
. - Automatic Reconnection: If the
auto_reconnect
property istrue
, the client will automatically attempt to reconnect if the connection is closed unexpectedly. It uses an exponential backoff strategy (increasing delays between attempts) managed by the internal_tries
counter to avoid spamming connection requests. - State Tracking: Monitors the underlying
WebSocketPeer.State
and emits signals when the state changes, particularly on connection establishment and closure. - Message Handling: Receives incoming WebSocket messages and emits them as raw
PackedByteArray
via themessage_received
signal. - Sending: Provides a simple method (
send_text
) for sending string data over the connection.
The client performs its checks and connection attempts within the _process
loop by calling its internal _poll
method.
Prerequisites
- Add the Node: Add a
WebsocketClient
node to your scene tree.
Configuration (Inspector Properties)
Connection Url
(String
): Required. The full URL of the WebSocket server to connect to (e.g., "wss://yourserver.com/socket"). The client will not attempt to connect if this is empty.Auto Reconnect
(bool
): Iftrue
, the client will automatically attempt to reconnect after a connection loss, using exponential backoff. Iffalse
, it will remain closed untilopen_connection()
is called again. Setting this property directly can influence connection behavior.
Signals
connection_established
- Emitted when the WebSocket connection state transitions to
WebSocketPeer.STATE_OPEN
. This signifies that the client is ready to send and receive data.
- Emitted when the WebSocket connection state transitions to
connection_closed
- Emitted when the WebSocket connection state transitions to
WebSocketPeer.STATE_CLOSED
, either intentionally viaclose()
or due to network issues/server disconnection.
- Emitted when the WebSocket connection state transitions to
message_received(message: PackedByteArray)
- Emitted when a complete WebSocket message packet is received from the server.
message
: The raw data received as aPackedByteArray
. You will likely need to convert this (e.g., usingmessage.get_string_from_utf8()
) depending on the expected data format.
connection_state_changed(state: WebSocketPeer.State)
- Emitted whenever the underlying
WebSocketPeer
's ready state changes. state
: The newWebSocketPeer.State
enum value (e.g.,STATE_CONNECTING
,STATE_OPEN
,STATE_CLOSING
,STATE_CLOSED
).
- Emitted whenever the underlying
Key Public Methods
open_connection() -> void
- Manually initiates the connection process. Sets
auto_reconnect
totrue
and begins attempts to establish a connection (using_establish_connection
internally, which includes delays). - Note: This method triggers an asynchronous process. Use
await wait_connection_established()
or theconnection_established
signal to know when the connection is actually open.
- Manually initiates the connection process. Sets
wait_connection_established() -> void
- An asynchronous utility function. If the connection is not currently open (
is_open
is false), it waits until theconnection_established
signal is emitted. Useawait
when calling this to pause execution until connected.
- An asynchronous utility function. If the connection is not currently open (
send_text(message: String) -> Error
- Sends the provided
message
string as a text frame over the WebSocket connection.
- Sends the provided
close(status: int = 1000, message: String = "Normal Closure") -> void
- Manually closes the WebSocket connection with the specified status code and reason message.
- Important: Calling this method also sets
auto_reconnect
tofalse
, preventing automatic reconnection attempts after this intentional closure.
Properties (Read-Only Access)
connection_state
(WebSocketPeer.State
): Returns the current ready state of the underlyingWebSocketPeer
.is_open
(bool
): Returnstrue
ifconnection_state
isWebSocketPeer.STATE_OPEN
,false
otherwise.is_closed
(bool
): Returnstrue
ifconnection_state
isWebSocketPeer.STATE_CLOSED
,false
otherwise.
Usage Example
gdscript
extends Node
@onready var ws_client: WebsocketClient = $WebsocketClient # Assume added in scene
func _ready():
# Configure the client (alternatively, set these in the Inspector)
ws_client.connection_url = "wss://your-websocket-server.com"
# Connect signals
ws_client.connection_established.connect(_on_ws_connected)
ws_client.connection_closed.connect(_on_ws_disconnected)
ws_client.message_received.connect(_on_ws_message)
ws_client.connection_state_changed.connect(_on_ws_state_changed)
print("Attempting to open WebSocket connection...")
# Start the connection process (it runs asynchronously)
ws_client.open_connection()
func _on_ws_connected():
print("WebSocket Connected!")
# Now it's safe to send messages
ws_client.send_text("Hello from Godot WebsocketClient!")
func _on_ws_disconnected():
print("WebSocket Disconnected!")
# UI can be updated here. If auto_reconnect is true, it will try connecting again.
func _on_ws_message(message_bytes: PackedByteArray):
var message_string := message_bytes.get_string_from_utf8()
print("WebSocket Message Received: %s" % message_string)
# Process the received message
func _on_ws_state_changed(new_state: WebSocketPeer.State):
print("WebSocket State Changed: %s" % new_state) # Print state name
# Example: Send data on button press (ensure connection is open)
func _send_test_message():
if ws_client.is_open:
ws_client.send_text("Button was pressed!")
else:
print("Cannot send message, WebSocket is not open.")
# Ensure clean disconnect when closing the game
func _notification(what):
if what == NOTIFICATION_WM_CLOSE_REQUEST:
if ws_client and not ws_client.is_closed:
print("Closing WebSocket connection on exit...")
ws_client.close(1000, "Client exiting")