Connecting basics
To make a connection to the Diffusion™ server the client must specify the host name and port number of the Diffusion server , the transport to use to connect, and whether that connection is secure.
The Diffusion API is an asynchronous API. As such, the client APIs for all languages provide asynchronous connect methods.
A subset of the Diffusion APIs also provide synchronous connect methods: the Android™ , Java™ , .NET, and C APIs. In the following sections, all examples for these APIs are synchronous for simplicity. For asynchronous examples for these APIs, see Asynchronous Connections.
Connection parameters
- host
- The host name or IP address of the system on which the Diffusion server is located.
- port
- The port on which the Diffusion server accepts connections from clients using the Diffusion API. You can configure which ports to provide connectors for in the Connectors.xml configuration file. For more information, see Configuring Connectors.
- transport
- The transport used to make the connection. For example, WebSocket (ws). The transports your client can use to make a connection depend on the client library capabilities. For more information, see Support Platforms.
- secure
- Whether the connection is made over Secure Sockets Layer (SSL) .
Connecting
In JavaScript® , Android and Java , you can define each of these parameters individually:
// Excluding the port from the URL defaults to 80, or 443 for secure connections diffusion.connect({ host : 'host_url', }).then((session) => { // Ensure to maintain a reference to the session beyond the lifetime // of this callback, for example by assigning it to an instance variable. // At this point we now have a connected session. console.log('Connected'); }).catch((error) => { console.error('Failed to create session!', error); });
final Session session = Diffusion .sessions() .principal("client") .password("password") .transports(Transport.WEBSOCKET) .secureTransport(false) .serverHost("localhost") .serverPort(8080) .open();
In Apple® , Android , Java , .NET and C, composite the host, port, transport, and whether the connection is secure into a single URL-style string of the following form: transport[s]://host:port.
For example, ws://diffusion.example.com:8080.
Use this URL to open the connection to the Diffusion server :
var session = Diffusion.Sessions.Open("url");
final Session session = Diffusion .sessions() .principal("client") .password("password") .open("ws://localhost:8080");
SESSION_T *session = session_create(url, principal, credentials, NULL, NULL, NULL);
// Excluding the port from the URL defaults to 80, or 443 for secure connections PTDiffusionSession.open(with: URL(string: "url")!) { (session, error) in // Check error is `nil`, then use session as required. // Ensure to maintain a strong reference to the session beyond the lifetime // of this callback, for example by assigning it to an instance variable. if (session == nil) { print("Failed to open session: %@", error!.localizedDescription) return } // At this point we now have a connected session. print("Connected.") }
Initial Session Establishment Retry Strategy
All Diffusion APIs can define an initial session establishment retry strategy to connect to the Diffusion server , specifying the number of attempts and the interval in milliseconds between retry attempts. This is in addition to the reconnection strategy which is enabled by default for already connected clients.
diffusion.connect({ host : 'host_url', // It will attempt 5 times to connect to the Diffusion server, // with 100 milliseconds interval between attempts. retry : { attempts: 5, interval: 100 } }).then((session) => { // ... })
// Create an initial session establishment retry strategy. // It will attempt 5 times to connect to the Diffusion server, // with 100 milliseconds interval between attempts. var retryStrategy = new RetryStrategy(100, 5); var session = Diffusion.Sessions .Principal("admin") .Password("password") .CertificateValidation((cert, chain, errors) => CertificateValidationResult.ACCEPT) .InitialRetryStrategy(retryStrategy) .Open(serverUrl); // ... session.Close();
// It will attempt 5 times to connect to the Diffusion server, // with 100 milliseconds interval between attempts. final Session session = Diffusion.sessions() .serverHost("localHost") .serverPort(8080) .initialRetryStrategy(new RetryStrategy(100, 5)) .open();
// Create a session factory and configure the principal and credentials, if required. DIFFUSION_SESSION_FACTORY_T *session_factory = diffusion_session_factory_init(); diffusion_session_factory_principal(session_factory, principal); diffusion_session_factory_credentials(session_factory, credentials); // Create an initial session establishment retry strategy. // It will attempt 10 times to connect to the Diffusion server, with 500 milliseconds interval between attempts DIFFUSION_RETRY_STRATEGY_T *retry_strategy = diffusion_retry_strategy_create(500, 10, NULL); diffusion_session_factory_initial_retry_strategy(session_factory, retry_strategy); // Create a session, synchronously. SESSION_T *session = session_create_with_session_factory(session_factory, url); // ... session_close(session, NULL); session_free(session); diffusion_session_factory_free(session_factory);
# Create an initial session establishment retry strategy. # It will attempt 5 times to connect to the Diffusion server, # with 100 milliseconds interval between attempts. initial_retry_strategy = RetryStrategy(attempts=10, interval=5) async with ( diffusion.sessions() .principal(principal) .credentials(credentials) .initial_retry_strategy(initial_retry_strategy) .open(server_url) ) as session: _ = session pass
let configuration = PTDiffusionMutableSessionConfiguration() // Create an initial session establishment retry strategy. // It will attempt 10 times to connect to the Diffusion server, with 500 milliseconds interval between attempts. configuration.initialRetryStrategy = PTDiffusionRetryStrategy(interval: 500, andAttempts: 10); PTDiffusionSession.open(with: URL(string:"url")!, configuration: configuration) { (session, error) in // ... }
Connecting with multiple transports
In JavaScript , Android , and Java , you can specify a list of transports. The client uses these transports to provide a transport cascading capability.
// Excluding the port from the URL defaults to 80, or 443 for secure connections diffusion.connect({ host : 'host_url', // Try a websocket connection first. On failure cascade to XHR protocol transports : ['WEBSOCKET', 'XHR'] }).then((session) => { // Ensure to maintain a reference to the session beyond the lifetime // of this callback, for example by assigning it to an instance variable. // At this point we now have a connected session. console.log(`Connected with session ID ${session.sessionId.toString()}`); }).catch((error) => { console.error('Failed to create session!', error); });
final Session session = Diffusion .sessions() .principal("client") .password("password") .serverHost("localhost") .serverPort(8080) .transports(Transport.WEBSOCKET, Transport.HTTP_POLLING) .open();
- The client attempts to connect using the first transport listed.
- If the connection is unsuccessful, the client attempts to connect using the next transport listed.
- This continues until the one of the following events happens:
- The client makes a connection
- The client has attempted to make a connection using every listed transport. If this happens, the connection fails.
You can use specify that a client attempt to connect with a transport more than once. This enables you to define retry behavior. For example:
transports: ['WS', 'XHR', 'WS']
Transport cascading is useful to specify in your clients as it enables them to connect from many different environments. Factors such as the firewall in use, your end-user's mobile provider, or your end-user's browser can affect which transports can successfully make a connection to the Diffusion server .
Asynchronous connections
All Diffusion APIs can connect asynchronously to the Diffusion server :
try { // You can make asynchronous calls using async-await syntax const session = await diffusion.connect({ host : 'host_url' }); // At this point we now have a connected session. console.log('Connected'); } catch(error) { console.error('Failed to create session!', error); }
Diffusion.Sessions.Principal("client") .Credentials(Diffusion.Credentials.Password("password")) .CertificateValidation((cert, chain, errors) => CertificateValidationResult.ACCEPT) .Open(serverUrl, new SessionOpenCallback()); ... /// <summary> /// Callback used when a session is opened using ISessionFactory.Open /// </summary> private sealed class SessionOpenCallback : ISessionOpenCallback { public void OnError(ErrorReason errorReason) => WriteLine($"An error occurred: {errorReason}"); public void OnOpened(ISession session) { WriteLine("Session opened."); session.Close(); WriteLine("Session closed."); } }
Diffusion.sessions().openAsync("ws://localhost:8080") .thenApply(session -> { // do work here return session.getSessionId(); });
static int on_session_connected(SESSION_T *session) { // Invoked if the client can successfully connect to Diffusion, // and a session instance is ready for use. return HANDLER_SUCCESS; } static int on_session_error(SESSION_T *session, DIFFUSION_ERROR_T *error) { // Invoked if there is an error connection to the Diffusion server. return HANDLER_SUCCESS; } ... SESSION_CREATE_CALLBACK_T callbacks = { .on_connected = on_session_connected, .on_error = on_session_error }; SESSION_T *session = session_create_async( url, principal, credentials, NULL, // session listener NULL, // reconnection strategy &callbacks, NULL); // error
// Excluding the port from the URL defaults to 80, or 443 for secure connections PTDiffusionSession.open(with: URL(string: "url")!) { (session, error) in // Check error is `nil`, then use session as required. // Ensure to maintain a strong reference to the session beyond the lifetime // of this callback, for example by assigning it to an instance variable. if (session == nil) { print("Failed to open session: %@", error!.localizedDescription) return } // At this point we now have a connected session. print("Connected.") }
Synchronous connections
The following APIs can connect synchronously to the Diffusion server :
var session = Diffusion.Sessions.Open("url");
final Session session = Diffusion.sessions().open("ws://localhost:8080");
SESSION_T *session = session_create( url, principal, credentials, NULL, // session listener NULL, // reconnection strategy NULL // error );
When connecting to the Diffusion server using the Android API, prefer the asynchronous open() method with a callback. Using the synchronous open() method might open a connection on the same thread as the UI and cause a runtime exception. However, the synchronous open() method can be used in any thread that is not the UI thread.
Managing your session
When your client has opened a session with the Diffusion server , you can listen for session events to be notified when the session state changes. For more information about session states, see Session state.
JavaScript
- disconnect: The session has lost connection to
the
Diffusion
server
.
The session state changes from CONNECTED_ACTIVE to RECOVERING_RECONNECT. This event is only emitted if reconnect is enabled.
- reconnect: The session has re-established connection to
the
Diffusion
server
.
The session state changes from RECOVERING_RECONNECT to CONNECTED_ACTIVE.
- close: The session has closed. The provided close
reason indicates whether this was caused by the client,
the
Diffusion
server
, a failure to connect, or an error.
The session state changes to one of CLOSED_FAILED, CLOSED_BY_SERVER, or CLOSED_BY_CLIENT.
- error: A session error occurs.
session.on('disconnect', () => { console.log('Lost connection to the server.'); }); session.on('reconnect', () => { console.log('Reconnected to the session on the server.'); }); session.on('close', () => { console.log('Session is closed.'); }); session.on('error', () => { console.log('A session error occurred.'); });
Apple
- isConnected: If true, the state is equivalent to the CONNECTED_ACTIVE state.
- isRecovering: If true, the state is equivalent to the RECOVERING_RECONNECT state.
- isClosed: If true, the state is one of CLOSED_FAILED, CLOSED_BY_SERVER, or CLOSED_BY_CLIENT.
The broadcast includes both the old state and new state of the session. It also includes an error property that is nil unless the session closure was caused by a failure.
let notification_center = NotificationCenter.default notification_center .addObserver(forName: NSNotification.Name.PTDiffusionSessionStateDidChange, object: session, queue: nil) { (notification) in let change = notification.userInfo![PTDiffusionSessionStateChangeUserInfoKey]! print("Session state change: %@", change) }
Other SDKs
In Android , Java , .NET, and C listen for changes to the session state. The listener provides both the old state and new state of the session. The states provided are those listed in the session state diagram. For more information, see Session state.
private void OnSessionStateChanged(object sender, SessionListenerEventArgs e) { WriteLine($"State changed from {e.OldState} to {e.NewState}."); } ... var session = Diffusion.Sessions .Principal("admin") .Credentials(Diffusion.Credentials.Password("password")) .SessionStateChangedHandler(OnSessionStateChanged) .Open(serverUrl);
// Add the listener to the session session.addListener(new Listener() { @Override public void onSessionStateChanged(Session session, State oldState, State newState) { System.out.println("Session state changed from " + oldState.toString() + " to " + newState.toString()); } });
static void on_session_state_changed( SESSION_T *session, const SESSION_STATE_T old_state, const SESSION_STATE_T new_state) { printf("Session state changed from %s (%d) to %s (%d)\n", session_state_as_string(old_state), old_state, session_state_as_string(new_state), new_state); } ... SESSION_LISTENER_T listener = { .on_state_changed = on_session_state_changed }; SESSION_T *session = session_create( url, principal, credentials, &listener, NULL, // reconnection strategy NULL // error );