neuray API Programmer's Manual

Example for Networking modes

[Previous] [Next] [Up]

This example starts the neuray API in different networking modes.

New Topics

  • Starting and configuring different networking modes

Detailed Description

General

This example just shows the basic configuration options to set up the different networking modes. Further configuration options related to networking are provided by the mi::neuraylib::INetwork_configuration interface. A simple implementation of the mi::neuraylib::IHost_callback interface is used to track network changes.

See also Networking Configuration for a general discussion about the advantages and disadvantages of the available networking modes.

No networking

This mode is the default, since it does not require any additional configuration. In this mode each instance of the neuray API is separate. There are no attempts to connect to other instances. This mode was already used in the previous examples. It is part of this example program just for a matter of completeness.

UDP mode

The UDP mode is the simplest networking mode (apart from no networking at all). All it requires is an UDP multicast address and port number. All hosts with instances of the neuray API than can be reached via this multicast address join a single cluster. The cluster can be restricted to certain set of hosts by using an optional discovery identifier. This option allows a fine-grained control over potential members of a particular cluster.

TCP mode

In TCP mode it is necessary to specify all hosts participating in the cluster in advance. Apart from your address and port, you have to specify the addresses and ports of all other hosts. Since this mode is not very flexible it is recommended to use TCP mode with discovery instead.

TCP mode with discovery

This mode is similar to TCP, but there is a discovery mechanism which eliminates the need to specify the addresses and ports of all other hosts. There are two variants of this mode: discovery via multicast or discovery via a master node. In the multicast variant you have to specify a common multicast address which is used by all hosts during the discovery phase to join the cluster. In the master variant you have to specify a common unicast address. The host with the given IP address acts as master during the discovery phase, all other hosts connect to this host to join the cluster. In both variants TCP is used as in the TCP mode without discovery after the host connected to the cluster. Similar to the UDP mode an optional discovery identifier can be used to restrict the cluster to a certain set of hosts.

Example Source

Source Code Location: examples/example_networking.cpp

‎/******************************************************************************
 * Copyright 1986, 2011 NVIDIA Corporation. All rights reserved.
 *****************************************************************************/

// examples/example_networking.cpp
//
// Demonstrates usage of the different networking modes

#include <mi/neuraylib.h>

// Include code shared by all examples.
#include "example_shared.h"

// This example implementation of the IHost_callback interface just prints a line
// for every event.
class Host_callback : public mi::base::Interface_implement<mi::neuraylib::IHost_callback>
{
public:
    void membership_callback( mi::Uint32 host_id, bool flag)
    {
        if( flag)
            printf( "Host %d joined the cluster.\n", host_id);
        else
            printf( "Host %d left the cluster.\n", host_id);
    }
    void property_callback( mi::Uint32 host_id, const mi::neuraylib::IHost_properties *properties)
    {
        printf( "Host %d communicated its properties.\n", host_id);
        mi::base::Handle< const mi::IString> value( properties->get_property( "application_name"));
        if( value.is_valid_interface())
            printf("application_name: %s\n", value->get_c_str());
    }
    void connection_callback( mi::Uint32 host_id, bool flag)
    {
        if( flag) {
            printf( "The connection to the cluster was established. Own host id is %d.\n", host_id);
            m_own_host_id = host_id;
        }
        else
            printf( "The connection to the cluster was lost.\n");
    }
    void database_status_callback( const char* status)
    {
        printf( "The database reports its status as \"%s\".\n", status);
    }
    void synchronizer_callback(mi::Uint32 host_id)
    {
        printf( "The synchronizer is now host %d", host_id);
        if( m_own_host_id == host_id)
            printf( " (this host)");
        printf( ".\n");
    }

    mi::Uint32 m_own_host_id;
};

void configuration( mi::base::Handle< mi::neuraylib::INeuray> neuray,
                    mi::base::Handle< mi::neuraylib::IHost_callback> host_callback,
                    int argc,
                    char* argv[])
{
    mi::base::Handle< mi::neuraylib::INetwork_configuration> network_configuration(
        neuray->get_api_component<mi::neuraylib::INetwork_configuration>());

    // Install callback handler
    network_configuration->set_host_callback( host_callback.get());

    check_success( argc >= 5);

    // Set networking mode
    const char *mode = argv[1];
    if( strcmp( mode, ".") == 0) {
        ;
    } else if( strcmp( mode, "OFF") == 0) {
        check_success( network_configuration->set_mode(
            mi::neuraylib::INetwork_configuration::MODE_OFF) == 0);
    } else if( strcmp( mode, "TCP") == 0) {
        check_success( network_configuration->set_mode(
            mi::neuraylib::INetwork_configuration::MODE_TCP) == 0);
    } else if( strcmp( mode, "UDP") == 0) {
        check_success( network_configuration->set_mode(
            mi::neuraylib::INetwork_configuration::MODE_UDP) == 0);
    } else if( strcmp( mode, "TCP_WITH_DISCOVERY") == 0) {
        check_success( network_configuration->set_mode(
            mi::neuraylib::INetwork_configuration::MODE_TCP_WITH_DISCOVERY) == 0);
    } else {
        check_success( false);
    }

    // Set the multicast address
    if( strcmp( argv[2], ".") != 0)
        check_success( network_configuration->set_multicast_address( argv[2]) == 0);

    // Set the cluster interface
    if( strcmp( argv[3], ".") != 0)
        check_success( network_configuration->set_cluster_interface( argv[3]) == 0);

    // Set the discovery address
    if( strcmp( argv[4], ".") != 0)
        check_success( network_configuration->set_discovery_address( argv[4]) == 0);

    // Add configured hosts
    for( int i = 5; i < argc; ++i)
        check_success( network_configuration->add_configured_host( argv[i]) == 0);

    // Set a host property
    mi::base::Handle< mi::neuraylib::IGeneral_configuration> general_configuration(
        neuray->get_api_component<mi::neuraylib::IGeneral_configuration>());
    general_configuration->set_host_property( "application_name", "example_networking");
}

void print_configuration( mi::base::Handle< mi::neuraylib::INeuray> neuray)
{
    mi::base::Handle< mi::neuraylib::INetwork_configuration> network_configuration(
        neuray->get_api_component<mi::neuraylib::INetwork_configuration>());

    // Print networking mode
    mi::neuraylib::INetwork_configuration::Mode mode = network_configuration->get_mode();
    switch( mode) {
        case mi::neuraylib::INetwork_configuration::MODE_OFF:
            printf( "mode: OFF\n");
            break;
        case mi::neuraylib::INetwork_configuration::MODE_TCP:
            printf( "mode: TCP\n");
            break;
        case mi::neuraylib::INetwork_configuration::MODE_UDP:
            printf( "mode: UDP\n");
            break;
        case mi::neuraylib::INetwork_configuration::MODE_TCP_WITH_DISCOVERY:
            printf( "mode: TCP_WITH_DISCOVERY\n");
            break;
        default:
            printf( "mode: error\n");
            break;
    }

    // Print the multicast address
    mi::base::Handle< const mi::IString> string( network_configuration->get_multicast_address());
    printf( "multicast address: %s\n", string->get_c_str());

    // Print the cluster interface
    string = network_configuration->get_cluster_interface();
    printf( "cluster interface: %s\n", string->get_c_str());

    // Print the discovery address
    string = network_configuration->get_discovery_address();
    printf( "discovery address: %s\n", string->get_c_str());

    // Print the configured hosts
    printf( "configured hosts: ");
    for( mi::Uint32 i = 0; i < network_configuration->get_number_of_configured_hosts(); ++i) {
        string = network_configuration->get_configured_host( i);
        printf( "%s ", string->get_c_str());
    }
    printf( "\n");
}

// The example takes the following command line arguments:
//
//   example_networking <mode> <multicast_address> <cluster_interface> <discovery_address>
//                     [<host1> <host2> ... <hostN>]
//
// mode                          "OFF", "TCP", "UDP", "TCP_WITH_DISCOVERY"
// multicast_address             IPv4 or IPv6 address and port, or "."
// cluster_interface             IPv4 or IPv6 address and port, or "."
// discovery_address             IPv4 or IPv6 address and port, or "."
//
// The special value "." represents the "don't care" value for any address.
// If mode is "TCP", the remaining arguments are interpreted as hosts to configure.
//
// Examples:
//
//   No networking
//
//   @any host:    ./example_networking OFF . . .
//
//   UDP mode with three hosts
//
//   @192.168.1.1: ./example_networking UDP 224.1.1.1:1111 . .
//   @192.168.1.2: ./example_networking UDP 224.1.1.1:1111 . .
//   @192.168.1.3: ./example_networking UDP 224.1.1.1:1111 . .
//
//   TCP mode with three hosts
//
//   @192.168.1.1: ./example_networking TCP . 192.168.1.1:1111 . 192.168.1.2:2222 192.168.1.3:3333
//   @192.168.1.2: ./example_networking TCP . 192.168.1.2:2222 . 192.168.1.1:1111 192.168.1.3:3333
//   @192.168.1.3: ./example_networking TCP . 192.168.1.3:3333 . 192.168.1.1:1111 192.168.1.2:2222
//
//   TCP_WITH_DISCOVERY mode with three hosts (via multicast)
//
//   @192.168.1.1: ./example_networking TCP_WITH_DISCOVERY . 192.168.1.1:1111 224.1.1.1:4444
//   @192.168.1.2: ./example_networking TCP_WITH_DISCOVERY . 192.168.1.2:2222 224.1.1.1:4444
//   @192.168.1.3: ./example_networking TCP_WITH_DISCOVERY . 192.168.1.3:3333 224.1.1.1:4444
//
//   TCP_WITH_DISCOVERY mode with three hosts (via a master host)
//   Note that the master needs to be the only node running on its IP address.
//
//   @192.168.1.1: ./example_networking TCP_WITH_DISCOVERY . 192.168.1.1:1111 192.168.1.1:5555
//   @192.168.1.2: ./example_networking TCP_WITH_DISCOVERY . 192.168.1.2:2222 192.168.1.1:5555
//   @192.168.1.3: ./example_networking TCP_WITH_DISCOVERY . 192.168.1.3:3333 192.168.1.1:5555
//
int main( int argc, char* argv[])
{
    // Access the neuray library
    mi::base::Handle< mi::neuraylib::INeuray> neuray( load_and_get_ineuray());
    check_success( neuray.is_valid_interface());

    // Create callback handler
    mi::base::Handle< mi::neuraylib::IHost_callback> host_callback( new Host_callback());

    // Configure the neuray library
    configuration( neuray, host_callback, argc, argv);

    // Print the configuration
    print_configuration( neuray);

    // Start the neuray library
    check_success( neuray->start( true) == 0);

    // Wait for other hosts to join/leave the cluster. The Host_callback objects prints
    // messages of joining or leaving hosts.
    sleep_seconds( 30);

    // Shut down the neuray library
    check_success( neuray->shutdown() == 0);
    neuray = 0;

    // Unload the neuray library
    check_success( unload());

    return EXIT_SUCCESS;
}

[Previous] [Next] [Up]