Networking Sockets Manager - ArtyProf/steamworks-ffi-node GitHub Wiki
Networking Sockets Manager API Documentation
Complete reference for Steam Networking Sockets functionality in Steamworks FFI.
Overview
The SteamNetworkingSocketsManager provides access to the ISteamNetworkingSockets API, enabling peer-to-peer (P2P) connections between Steam users using Steam's relay network. This is the primary interface for implementing multiplayer networking in your game.
This manager is useful for:
- P2P Connections: Connect directly to other Steam users using their Steam ID
- Reliable Messaging: Send messages with configurable reliability and ordering
- Connection Management: Accept, close, and monitor connection states
- Poll Groups: Efficiently receive messages from multiple connections
- Event Callbacks: React to connection state changes in real-time
Quick Reference
| Category | Functions | Description |
|---|---|---|
| P2P Listen Sockets | 3 | Create, close, and list listen sockets |
| P2P Connections | 6 | Connect, accept, close, and track connections |
| Messaging | 5 | Send (reliable/unreliable) and receive messages |
| Connection Info | 7 | Query state, status, names, and user data |
| Poll Groups | 4 | Manage multiple connections efficiently |
| Identity & Auth | 3 | Get identity, init and check authentication |
| Callbacks | 5 | Handle events and run callback loop |
| Cleanup | 1 | Close all resources |
Total: 34 Functions
Connection States
Understanding connection states is crucial for P2P networking:
enum ESteamNetworkingConnectionState {
None = 0, // Not connected
Connecting = 1, // Attempting to connect
FindingRoute = 2, // Finding optimal route
Connected = 3, // Fully connected
ClosedByPeer = 4, // Remote peer closed
ProblemDetectedLocally = 5 // Local error occurred
}
P2P Listen Sockets
Functions for creating and managing P2P listen sockets.
createListenSocketP2P(virtualPort)
Creates a P2P listen socket to accept incoming connections from other Steam users.
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_CreateListenSocketP2P()- Create P2P listen socket
Parameters:
virtualPort: number- Virtual port number (0-based, default: 0)
Returns: HSteamListenSocket - Listen socket handle, or k_HSteamListenSocket_Invalid if failed
Example:
import SteamworksSDK, { k_HSteamListenSocket_Invalid } from 'steamworks-ffi-node';
const steam = SteamworksSDK.getInstance();
steam.init({ appId: 480 });
// Create a P2P listen socket on virtual port 0
const listenSocket = steam.networkingSockets.createListenSocketP2P(0);
if (listenSocket !== k_HSteamListenSocket_Invalid) {
console.log(`✅ Listening on socket: ${listenSocket}`);
console.log(`Your Steam ID: ${steam.getStatus().steamId}`);
console.log('Share this ID with other players to connect!');
}
closeListenSocket(listenSocket)
Closes a P2P listen socket.
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_CloseListenSocket()- Close listen socket
Parameters:
listenSocket: HSteamListenSocket- Listen socket handle
Returns: boolean - true if closed successfully
Example:
const success = steam.networkingSockets.closeListenSocket(listenSocket);
if (success) {
console.log('✅ Listen socket closed');
}
getActiveListenSockets()
Gets all currently active listen sockets.
Steamworks SDK Functions:
- Internal tracking - No direct SDK call (managed by wrapper)
Returns: HSteamListenSocket[] - Array of active listen socket handles
Example:
const sockets = steam.networkingSockets.getActiveListenSockets();
console.log(`Active listen sockets: ${sockets.length}`);
P2P Connections
Functions for establishing and managing P2P connections.
connectP2P(remoteSteamId, virtualPort)
Connects to another Steam user via P2P.
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_ConnectP2P()- Initiate P2P connection
Parameters:
remoteSteamId: string | bigint- Steam ID of the user to connect tovirtualPort: number- Virtual port number (must match host's listen port, default: 0)
Returns: HSteamNetConnection - Connection handle, or k_HSteamNetConnection_Invalid if failed
Example:
import { k_HSteamNetConnection_Invalid, ESteamNetworkingConnectionState } from 'steamworks-ffi-node';
const hostSteamId = '76561198012345678';
const connection = steam.networkingSockets.connectP2P(hostSteamId, 0);
if (connection !== k_HSteamNetConnection_Invalid) {
console.log(`✅ Connecting to ${hostSteamId}...`);
}
acceptConnection(connection)
Accepts an incoming connection request.
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_AcceptConnection()- Accept incoming connection
Parameters:
connection: HSteamNetConnection- Connection handle from connection request callback
Returns: EResult - Result code (EResult.OK on success)
Example:
steam.networkingSockets.onConnectionStateChange((change) => {
if (change.newState === ESteamNetworkingConnectionState.Connecting) {
// Incoming connection - accept it
const result = steam.networkingSockets.acceptConnection(change.connection);
if (result === EResult.OK) {
console.log('✅ Connection accepted');
}
}
});
closeConnection(connection, reason, debug, enableLinger)
Closes a connection with an optional reason.
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_CloseConnection()- Close connection
Parameters:
connection: HSteamNetConnection- Connection handle to closereason: number- Application-defined reason code (0 for normal)debug: string- Debug string (may be transmitted to remote)enableLinger: boolean- If true, waits for reliable messages to be delivered (default: false)
Returns: boolean - true if closed successfully
Example:
// Normal close
steam.networkingSockets.closeConnection(connection, 0, 'Game ended', false);
// Close with linger to ensure all messages delivered
steam.networkingSockets.closeConnection(connection, 0, 'Disconnect', true);
getActiveConnections()
Gets all currently active connections.
Steamworks SDK Functions:
- Internal tracking - No direct SDK call (managed by wrapper)
Returns: HSteamNetConnection[] - Array of active connection handles
Example:
const connections = steam.networkingSockets.getActiveConnections();
console.log(`Active connections: ${connections.length}`);
for (const conn of connections) {
const info = steam.networkingSockets.getConnectionInfo(conn);
console.log(` - ${info?.identityRemote}: ${info?.stateName}`);
}
isConnectionActive(connection)
Checks if a connection is currently tracked as active.
Steamworks SDK Functions:
- Internal tracking - No direct SDK call (managed by wrapper)
Parameters:
connection: HSteamNetConnection- Connection handle to check
Returns: boolean - true if the connection is active
Example:
if (steam.networkingSockets.isConnectionActive(connection)) {
// Safe to send messages
steam.networkingSockets.sendReliable(connection, 'Hello!');
}
Messaging
Functions for sending and receiving messages.
sendMessage(connection, data, flags)
Sends a message to a connected peer with custom flags.
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_SendMessageToConnection()- Send message with flags
Parameters:
connection: HSteamNetConnection- Connection handledata: Buffer | string- Message data to sendflags: number- Send flags (see below)
Send Flags:
const k_nSteamNetworkingSend_Unreliable = 0; // May be dropped, fastest
const k_nSteamNetworkingSend_NoNagle = 1; // Send immediately
const k_nSteamNetworkingSend_NoDelay = 4; // Bypass queue
const k_nSteamNetworkingSend_Reliable = 8; // Guaranteed delivery
const k_nSteamNetworkingSend_UseCurrentThread = 16;
Returns: SendMessageResult
interface SendMessageResult {
success: boolean;
result: EResult;
messageNumber: bigint;
}
Example:
// Send with custom flags (reliable + no delay)
const result = steam.networkingSockets.sendMessage(
connection,
JSON.stringify({ type: 'critical', data: '...' }),
8 | 4 // Reliable | NoDelay
);
sendReliable(connection, data)
Convenience method to send a reliable message (guaranteed delivery, ordered).
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_SendMessageToConnection()- Send with reliable flag
Parameters:
connection: HSteamNetConnection- Connection handledata: Buffer | string- Message data to send
Returns: SendMessageResult
Example:
// Send reliable message - guaranteed delivery
const result = steam.networkingSockets.sendReliable(connection, JSON.stringify({
type: 'chat',
message: 'Hello!'
}));
if (result.success) {
console.log(`Message sent, number: ${result.messageNumber}`);
}
sendUnreliable(connection, data)
Convenience method to send an unreliable message (fastest, may be dropped).
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_SendMessageToConnection()- Send with unreliable flag
Parameters:
connection: HSteamNetConnection- Connection handledata: Buffer | string- Message data to send
Returns: SendMessageResult
Example:
// Send unreliable message - fastest, for position updates
steam.networkingSockets.sendUnreliable(connection, JSON.stringify({
type: 'position',
x: player.x,
y: player.y,
timestamp: Date.now()
}));
flushMessages(connection)
Flushes any pending outgoing messages immediately.
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_FlushMessagesOnConnection()- Flush pending messages
Parameters:
connection: HSteamNetConnection- Connection handle
Returns: EResult - Result code
Example:
// Send critical message and flush immediately
steam.networkingSockets.sendReliable(connection, criticalData);
steam.networkingSockets.flushMessages(connection);
receiveMessages(connection, maxMessages)
Receives pending messages from a specific connection.
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_ReceiveMessagesOnConnection()- Receive messages
Parameters:
connection: HSteamNetConnection- Connection handlemaxMessages: number- Maximum messages to retrieve (default: 16)
Returns: NetworkMessage[]
Type:
interface NetworkMessage {
data: Buffer; // Message payload
size: number; // Size in bytes
connection: HSteamNetConnection; // Connection it came from
identity: string; // Sender's Steam ID
channel: number; // Lane/channel number
flags: number; // Message flags
messageNumber: bigint; // Sequence number
}
Example:
// Receive loop
const messages = steam.networkingSockets.receiveMessages(connection, 50);
for (const msg of messages) {
const text = msg.data.toString('utf8');
console.log(`📨 Received from ${msg.identity}: ${text}`);
try {
const data = JSON.parse(text);
handleGameMessage(data);
} catch {
handleTextMessage(text);
}
}
Connection Info
Functions for querying connection state and status.
getConnectionInfo(connection)
Gets information about a connection's current state.
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_GetConnectionInfo()- Get connection info
Parameters:
connection: HSteamNetConnection- Connection handle
Returns: ConnectionInfo | null
Type:
interface ConnectionInfo {
identityRemote: string; // Remote peer's Steam ID
userData: bigint; // Application user data
listenSocket: HSteamListenSocket; // Listen socket (if incoming)
remoteAddress: string; // Remote address
popIdRemote: number; // Remote POP ID
popIdRelay: number; // Relay POP ID
state: ESteamNetworkingConnectionState;
stateName: string; // Human-readable state
endReason: number; // Close reason code
endDebugMessage: string; // Close reason message
connectionDescription: string; // Debug description
}
Example:
const info = steam.networkingSockets.getConnectionInfo(connection);
if (info) {
console.log(`Remote peer: ${info.identityRemote}`);
console.log(`State: ${info.stateName} (${info.state})`);
if (info.state === ESteamNetworkingConnectionState.ClosedByPeer) {
console.log(`Closed: ${info.endDebugMessage}`);
}
}
getConnectionRealTimeStatus(connection)
Gets real-time connection status including quality metrics.
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_GetConnectionRealTimeStatus()- Get real-time status
Parameters:
connection: HSteamNetConnection- Connection handle
Returns: ConnectionRealTimeStatus | null
Type:
interface ConnectionRealTimeStatus {
state: ESteamNetworkingConnectionState;
ping: number; // Round-trip time in ms
connectionQualityLocal: number; // 0-1 quality estimate
connectionQualityRemote: number; // 0-1 quality estimate
outPacketsPerSec: number;
outBytesPerSec: number;
inPacketsPerSec: number;
inBytesPerSec: number;
sendRateBytesPerSecond: number;
pendingUnreliable: number; // Unreliable bytes queued
pendingReliable: number; // Reliable bytes queued
sentUnackedReliable: number; // Sent but unacked bytes
queueTime: bigint; // Microseconds in queue
}
Example:
const status = steam.networkingSockets.getConnectionRealTimeStatus(connection);
if (status) {
console.log(`Ping: ${status.ping}ms`);
console.log(`Quality: ${(status.connectionQualityLocal * 100).toFixed(1)}%`);
console.log(`In: ${status.inBytesPerSec} B/s, Out: ${status.outBytesPerSec} B/s`);
}
getDetailedConnectionStatus(connection)
Gets detailed connection status as a human-readable string.
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_GetDetailedConnectionStatus()- Get detailed status
Parameters:
connection: HSteamNetConnection- Connection handle
Returns: string - Detailed status text
Example:
const details = steam.networkingSockets.getDetailedConnectionStatus(connection);
console.log('Connection Details:');
console.log(details);
// Shows ping, packet loss, bandwidth, route info, etc.
setConnectionUserData(connection, userData)
Sets application-specific data on a connection.
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_SetConnectionUserData()- Set user data
Parameters:
connection: HSteamNetConnection- Connection handleuserData: bigint- Application-defined data
Returns: boolean - true if set successfully
Example:
// Store player ID with connection
const playerId = BigInt(12345);
steam.networkingSockets.setConnectionUserData(connection, playerId);
getConnectionUserData(connection)
Gets application-specific data from a connection.
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_GetConnectionUserData()- Get user data
Parameters:
connection: HSteamNetConnection- Connection handle
Returns: bigint - User data value, or -1n if invalid
Example:
const playerId = steam.networkingSockets.getConnectionUserData(connection);
if (playerId !== BigInt(-1)) {
console.log(`Player ID: ${playerId}`);
}
setConnectionName(connection, name)
Sets a debug name for a connection (useful for logging).
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_SetConnectionName()- Set connection name
Parameters:
connection: HSteamNetConnection- Connection handlename: string- Debug name
Example:
steam.networkingSockets.setConnectionName(connection, 'Player1-GameSession');
getConnectionName(connection)
Gets the debug name for a connection.
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_GetConnectionName()- Get connection name
Parameters:
connection: HSteamNetConnection- Connection handle
Returns: string - Connection name, or empty string
Example:
const name = steam.networkingSockets.getConnectionName(connection);
console.log(`Connection: ${name}`);
Poll Groups
Functions for efficiently managing multiple connections.
createPollGroup()
Creates a poll group to receive messages from multiple connections at once.
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_CreatePollGroup()- Create poll group
Returns: HSteamNetPollGroup - Poll group handle, or k_HSteamNetPollGroup_Invalid if failed
Example:
import { k_HSteamNetPollGroup_Invalid } from 'steamworks-ffi-node';
const pollGroup = steam.networkingSockets.createPollGroup();
if (pollGroup !== k_HSteamNetPollGroup_Invalid) {
console.log(`✅ Created poll group: ${pollGroup}`);
}
destroyPollGroup(pollGroup)
Destroys a poll group.
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_DestroyPollGroup()- Destroy poll group
Parameters:
pollGroup: HSteamNetPollGroup- Poll group handle
Returns: boolean - true if destroyed successfully
setConnectionPollGroup(connection, pollGroup)
Adds a connection to a poll group.
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_SetConnectionPollGroup()- Set poll group
Parameters:
connection: HSteamNetConnection- Connection handlepollGroup: HSteamNetPollGroup- Poll group handle
Returns: boolean - true if added successfully
Example:
// Add all connections to a poll group for efficient message receiving
const pollGroup = steam.networkingSockets.createPollGroup();
steam.networkingSockets.onConnectionStateChange((change) => {
if (change.newState === ESteamNetworkingConnectionState.Connected) {
steam.networkingSockets.setConnectionPollGroup(change.connection, pollGroup);
}
});
receiveMessagesOnPollGroup(pollGroup, maxMessages)
Receives messages from all connections in a poll group.
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_ReceiveMessagesOnPollGroup()- Receive from poll group
Parameters:
pollGroup: HSteamNetPollGroup- Poll group handlemaxMessages: number- Maximum messages to retrieve (default: 64)
Returns: NetworkMessage[] - Array of messages with connection info
Example:
// Efficient multi-connection receive loop
const messages = steam.networkingSockets.receiveMessagesOnPollGroup(pollGroup, 100);
for (const msg of messages) {
console.log(`📨 From connection ${msg.connection}: ${msg.data.toString()}`);
handleMessage(msg.connection, msg.data);
}
Identity & Auth
Functions for identity and authentication.
getIdentity()
Gets the local user's networking identity (Steam ID).
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_GetIdentity()- Get local identity
Returns: string | null - Steam ID as string, or null if not available
Example:
const identity = steam.networkingSockets.getIdentity();
if (identity) {
console.log(`Local Steam ID: ${identity}`);
}
initAuthentication()
Initializes authentication for networking.
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_InitAuthentication()- Initialize auth
Returns: number - Status code (ESteamNetworkingAvailability)
Example:
const status = steam.networkingSockets.initAuthentication();
console.log(`Authentication init status: ${status}`);
getAuthenticationStatus()
Gets the current authentication status.
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_GetAuthenticationStatus()- Get auth status
Returns: number - Status code (ESteamNetworkingAvailability)
Example:
const status = steam.networkingSockets.getAuthenticationStatus();
console.log(`Authentication status: ${status}`);
Callbacks
Functions for handling events and running the callback loop.
runCallbacks()
Processes pending networking callbacks. Must be called regularly (e.g., every frame).
Steamworks SDK Functions:
- Internal callback processing - Polls
SteamNetConnectionStatusChangedCallback_t
Example:
// Game loop - call frequently
setInterval(() => {
steam.runCallbacks(); // Steam callbacks
steam.networkingSockets.runCallbacks(); // Networking callbacks
}, 16); // ~60 FPS
onConnectionStateChange(handler)
Registers a handler for connection state changes.
Steamworks SDK Functions:
- Callback:
SteamNetConnectionStatusChangedCallback_t
Parameters:
handler: (change: ConnectionStateChange) => void
Type:
interface ConnectionStateChange {
connection: HSteamNetConnection;
oldState: ESteamNetworkingConnectionState;
newState: ESteamNetworkingConnectionState;
info: ConnectionInfo;
}
Returns: () => void - Unregister function
Example:
const unregister = steam.networkingSockets.onConnectionStateChange((change) => {
console.log(`Connection ${change.connection}: ${change.info.stateName}`);
if (change.newState === ESteamNetworkingConnectionState.Connecting) {
// Incoming connection on listen socket - accept it
steam.networkingSockets.acceptConnection(change.connection);
}
if (change.newState === ESteamNetworkingConnectionState.Connected) {
console.log('✅ Connected!');
}
if (change.newState === ESteamNetworkingConnectionState.ClosedByPeer ||
change.newState === ESteamNetworkingConnectionState.ProblemDetectedLocally) {
console.log(`❌ Disconnected: ${change.info.endDebugMessage}`);
}
});
// Later: stop handling
unregister();
onConnectionRequest(handler)
Registers a handler for incoming connection requests (on listen sockets).
Steamworks SDK Functions:
- Callback:
SteamNetConnectionStatusChangedCallback_t(when state isConnecting)
Parameters:
handler: (request: P2PConnectionRequest) => void
Type:
interface P2PConnectionRequest {
connection: HSteamNetConnection;
identityRemote: string;
listenSocket: HSteamListenSocket;
}
Returns: () => void - Unregister function
Example:
const unregister = steam.networkingSockets.onConnectionRequest((request) => {
console.log(`Connection request from: ${request.identityRemote}`);
// Note: You still need to accept via onConnectionStateChange
});
getPendingStateChanges()
Gets and clears pending state changes (alternative to callback handler).
Steamworks SDK Functions:
- Internal queue - Collects
SteamNetConnectionStatusChangedCallback_tevents
Returns: ConnectionStateChange[]
Example:
// Poll-based approach (alternative to onConnectionStateChange)
const changes = steam.networkingSockets.getPendingStateChanges();
for (const change of changes) {
handleStateChange(change);
}
getPendingConnectionRequests()
Gets and clears pending connection requests.
Steamworks SDK Functions:
- Internal queue - Filters incoming connection events from callbacks
Returns: P2PConnectionRequest[]
Cleanup
closeAll()
Closes all connections, listen sockets, and poll groups.
Steamworks SDK Functions:
SteamAPI_ISteamNetworkingSockets_CloseConnection()- For each connectionSteamAPI_ISteamNetworkingSockets_CloseListenSocket()- For each listen socketSteamAPI_ISteamNetworkingSockets_DestroyPollGroup()- For each poll group
Example:
// Cleanup on shutdown
process.on('SIGINT', () => {
steam.networkingSockets.closeAll();
steam.shutdown();
process.exit(0);
});
Complete P2P Example
Host (Server)
import SteamworksSDK, {
ESteamNetworkingConnectionState,
ESteamNetworkingAvailability,
k_HSteamListenSocket_Invalid,
k_HSteamNetPollGroup_Invalid,
EResult,
getConnectionStateName,
} from 'steamworks-ffi-node';
const steam = SteamworksSDK.getInstance();
steam.init({ appId: 480 });
// Initialize relay network
steam.networkingUtils.initRelayNetworkAccess();
// Wait for relay network to be ready
async function waitForRelay() {
while (true) {
steam.runCallbacks();
const status = steam.networkingUtils.getRelayNetworkStatus();
if (status.availability === ESteamNetworkingAvailability.Current) break;
await new Promise(r => setTimeout(r, 100));
}
}
await waitForRelay();
// Create listen socket and poll group
const listenSocket = steam.networkingSockets.createListenSocketP2P(0);
const pollGroup = steam.networkingSockets.createPollGroup();
console.log(`🎮 Host Steam ID: ${steam.getStatus().steamId}`);
console.log('Share this ID with players to connect!');
// Handle connections
steam.networkingSockets.onConnectionStateChange((change) => {
console.log(`State: ${getConnectionStateName(change.oldState)} -> ${getConnectionStateName(change.newState)}`);
if (change.newState === ESteamNetworkingConnectionState.Connecting) {
steam.networkingSockets.acceptConnection(change.connection);
steam.networkingSockets.setConnectionPollGroup(change.connection, pollGroup);
}
if (change.newState === ESteamNetworkingConnectionState.Connected) {
console.log(`✅ Player connected: ${change.info.identityRemote}`);
steam.networkingSockets.sendReliable(change.connection, 'Welcome!');
}
});
// Main loop
setInterval(() => {
steam.runCallbacks();
steam.networkingSockets.runCallbacks();
const messages = steam.networkingSockets.receiveMessagesOnPollGroup(pollGroup, 100);
for (const msg of messages) {
console.log(`📨 ${msg.identity}: ${msg.data.toString()}`);
}
}, 16);
Client (Joiner)
import SteamworksSDK, {
ESteamNetworkingConnectionState,
ESteamNetworkingAvailability,
k_HSteamNetConnection_Invalid,
getConnectionStateName,
} from 'steamworks-ffi-node';
const steam = SteamworksSDK.getInstance();
steam.init({ appId: 480 });
const hostSteamId = process.argv[2];
if (!hostSteamId) {
console.error('Usage: node client.js <host-steam-id>');
process.exit(1);
}
// Initialize relay network
steam.networkingUtils.initRelayNetworkAccess();
// Wait for relay, then connect
setTimeout(async () => {
const connection = steam.networkingSockets.connectP2P(hostSteamId, 0);
let connected = false;
steam.networkingSockets.onConnectionStateChange((change) => {
console.log(`State: ${getConnectionStateName(change.oldState)} -> ${getConnectionStateName(change.newState)}`);
if (change.newState === ESteamNetworkingConnectionState.Connected) {
connected = true;
console.log('✅ Connected to host!');
steam.networkingSockets.sendReliable(connection, 'Hello from client!');
}
});
// Main loop
setInterval(() => {
steam.runCallbacks();
steam.networkingSockets.runCallbacks();
if (connected) {
const messages = steam.networkingSockets.receiveMessages(connection, 50);
for (const msg of messages) {
console.log(`📨 Host: ${msg.data.toString()}`);
}
}
}, 16);
}, 2000);
Testing
Run the P2P networking tests:
Terminal 1 (Host):
npm run test:sockets:host:ts # TypeScript
npm run test:sockets:host:js # JavaScript
Terminal 2 (Client):
# Pass host's Steam ID, or run without args to enter manually
npm run test:sockets:join:ts -- 76561198012345678
npm run test:sockets:join:js -- 76561198012345678
Best Practices
- Always initialize relay network - Call
networkingUtils.initRelayNetworkAccess()and wait for it to be ready - Run callbacks frequently - Call both
steam.runCallbacks()andsteam.networkingSockets.runCallbacks()at least 60 times per second - Use poll groups for servers - More efficient than polling each connection individually
- Use event handlers -
onConnectionStateChange()is cleaner than pollinggetPendingStateChanges() - Choose appropriate send methods:
sendUnreliable()for position updates, inputs (fast, may drop)sendReliable()for chat, game events, important state (guaranteed)
- Clean up properly - Call
closeAll()on shutdown
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| Connection returns 0 | Invalid Steam ID or network not ready | Wait for relay network, verify Steam ID format |
| Messages not received | Not calling runCallbacks | Add both runCallbacks() calls to game loop |
| High latency | Using reliable for frequent updates | Use sendUnreliable() for position/input |
| Connection drops | Peer disconnected or network issue | Check connection state in callback |
Related Documentation
- Networking Utils Manager - Relay network status and ping estimation
- Matchmaking Manager - Steam lobbies for player discovery
- Friends Manager - Friend list for invites