ARTICLE

Introduction to the Real-Time C/C++ Docker Image

Jirapongse Phuriphanvichai
Developer Advocate Developer Advocate

Last Updated: June 2024

The Real-Time SDK is a suite of modern and open source APIs that is designed to simplify development through a strong focus on ease of use and standardized access to a broad set of LSEG and proprietary content and services.

It currently supports C, C++, and Java programming languages and can be run on several operating systems including Windows, Oracle Linux, Red Hat Enterprise Linux, and CentOS

Note: Although the Real-Time SDK can also run on Docker, it isn't officially qualified on the Docker platform. If you find any problems while running it on the Docker platform, the issues must be replicated on bare metal machines before contacting the helpdesk support.

This article demonstrates how to use the Real-Time SDK on the Docker platform. It has three sections including:

  • Real-Time APIs docker images on the Docker Hub
  • Deploying the Real-Time SDK C/C++ docker image
  • Running and modifying examples in the docker container 

Real-Time APIs docker images

The source of the Real-Time SDK is available in GitHub. The Real-Time SDK C/C++ and Java libraries can be built by using CMake and Gradle, respectively. Steps to build the Real-Time SDK libraries are mentioned in GitHub (C/C++, and Java). Moreover, you can create your own Real-Time SDK docker image by following steps in the Deploy and Run Real-Time SDK in Docker article.

Fortunately, the Real-Time SDK Docker images are now available in Docker Hub, as shown below.

  • lsegrealtime/realtimesdk_c: This docker image contains the latest version of Real-Time SDK C/C++ libraries and examples. The image is rebuilt when the new version of Real-Time SDK is available in GitHub. It uses Oracle Linux 7 as a based image and the GCC version is 4.8.5.
  • lsegrealtime/realtimesdk_java: This docker image contains the latest version of Real-Time SDK Java libraries and examples. The image is rebuilt when the new version of Real-Time SDK is available in GitHub. It uses Oracle Linux 7 as a based image and the Oracle OpenJDK version is 11.
  • lsegrealtime/websocket_api: This docker image contains WebSocket API Examples used to connect to Real-Time Distribution System or Data Platform to consume real-time data through the WebSocket connections. There are examples of various programming languages such as CSharp, Java, Python, Go, Ruby, Node, Perl, and R. The examples are available in GitHub. The image uses Oracle Linux 8 as a base image and it installs Python 3.9 used to run Python WebSocket API examples.

This article only focuses on the lsegrealtime/realtimesdk_c docker image.

In the next section, I will demonstrate how to deploy the lsegrealtime/realtimesdk_c image on Docker engines and Azure Containers.

Deploying the Real-Time SDK C/C++ docker image

The docker images can be run as docker containers on local machines or cloud platforms. To follow steps in this section, the docker engine must be installed on a local machine or an Azure account is ready to be used.

Deploying the Real-Time SDK C/C++ docker image on a local machine

First, the docker engine must be installed and run properly on the machine. The "docker version" command can be used to verify the docker engine.

    	
            

# docker version
Client: Docker Engine - Community
 Version:           19.03.1-ol
 API version:       1.40
 Go version:        go1.12.5
 Git commit:        ead9442
 Built:             Wed Sep 11 06:40:28 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.1-ol
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.5
  Git commit:       ead9442
  Built:            Wed Sep 11 06:38:43 2019
  OS/Arch:          linux/amd64
  Experimental:     false
  Default Registry: docker.io
 containerd:
  Version:          v1.2.0-rc.0-108-gc444666
  GitCommit:        c4446665cb9c30056f4998ed953e6d4ff22c7c39
 runc:
  Version:          1.0.0-rc5+dev
  GitCommit:        4bb1fe4ace1a32d3676bb98f5d3b6a4e32bf6c58
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

When the docker engine is started, the "docker pull lsegrealtime/realtimesdk_c" command can be used to download the latest Real-Time SDK C/C++ docker image from the Docker Hub.

    	
            

# docker pull lsegrealtime/realtimesdk_c

Using default tag: latest

Trying to pull repository docker.io/lsegrealtime/realtimesdk_c ...

latest: Pulling from docker.io/lsegrealtime/realtimesdk_c

01eb3c96478b: Already exists

ef4497be746b: Pull complete

Digest: sha256:4fd77224a4a4a72acb6cf0168fc59584b83bbf2b22f57a60bb7c5a5887f24da9

Status: Downloaded newer image for lsegrealtime/realtimesdk_c:latest

lsegrealtime/realtimesdk_c:latest

After downloading, the "docker images" command can be used to verify that the Real-Time SDK C/C++ docker image is available on the machine.

    	
            

# docker images

REPOSITORY                       TAG                 IMAGE ID            CREATED             SIZE

lsegrealtime/realtimesdk_c      latest              91e77e948e9f        3 hours ago         2.74GB

The output of the "docker images" command must contain the lsegrealtime/realtimesdk_c repository.

A Docker image can be run inside a container. The "docker run" command creates a new running container instance of the docker image. The following command can be used to run a container instance of the Real-Time SDK C/C++ docker image.

    	
            

# docker run -it --name realtimec lsegrealtime/realtimesdk_c

sh-4.2# ls

CHANGELOG.md  CMakeLists.txt  Ema  Eta  README.md  RTSDK-C-Edition_Test_Plan.xlsx  etc

sh-4.2# pwd

/opt/lseg/Real-Time-SDK/Cpp-C

After running this command, you can access shell in the container. Then, you run the Real-Time SDK examples in the container. The Real-Time SDK C/C++ is in /opt/lseg/Real-Time-SDK/Cpp-C directory.

Deploying the Real-Time SDK C/C++ docker image on Azure

Instead of running docker containers on the local machine, you can run the Real-Time SDK C/C++ docker container on Azure Container Instances. Azure Container Instances are used to create and manage Docker containers in Azure without having to set up virtual machines or manage additional infrastructure.

First, log in to Azure and then create a new Container Instances resource.

On the Create container instance page, fill in all required information. Select Docker Hub or other registry for the Image source and enter lsegrealtime/realtimesdk_c for the Image. Then, click on the Next: Networking button.

On the Networking tab, keep the default setting. Then click on the Next: Advanced button.

On the Advanced tab, enter [ "/bin/bash", "-c", "echo hello; sleep 60m" ] for the Command override. This command will keep the container running for 60 minutes before exiting. You can use another command or change the sleep time to keep the container running. Then, click on Review + create button.

Next, review the information and then click on the Create button to create a container instance.

Wait for the deployment process to be completed.

After the deployment is complete, click on the "Go to resource".

On the overview page, verify that the status of the container is Running.

Then, select Containers under Settings, click on the Connect tab, choose the shell to be used, and then click on the Connect button.

Now, you can access shell in the container.

Running examples in the container

This section demonstrates how to run EMA and ETA examples in the container to consume real-time data from Real-Time - Optimized. The Real-Time SDK C/C++ package is in the /opt/lseg/Real-Time-SDK/Cpp-C directory and the build directory is /opt/lseg/Real-Time-SDK/rtsdk/.

To access Real-Time -- Optimized, you should have a v1 authentication (Machine ID) or v2 authentication (Service account). These authentication accounts are used to get tokens. Then the tokens can be used to login to Real-Time – Optimized. For more information regarding v1 and v2 authentication, please refer to the Account authorization V1 to V2 migration cheat sheet article.

The v1 authentication comprises of:

  • Machine ID: A username in the form of GE-A-XXXXXXXX-X-XXXX
  • Password: A password for the machine ID
  • Client ID: A client ID or App Key that can be generated by using the AppKey Generator

The v2 authentication comprises of:

  • Client ID: A public identifier for apps
  • Client Secret: A secret known only to the application and the authorization server

Note: The client_id in the v2 authentication is not the same value as the client_id in the v1 authentication which is an app key.

Please find more detail from the following resources about the v2 authentication.

Note: After June 2024, the V1 authentication is only available for Wealth users. RTO uses must migrate to the v2 authentication. 

Running an EMA example

In the Real-Time SDK package, 113_MP_SessionMgmt is an OMM Consumer application example that demonstrates the basic usage of the EMA library in accessing and parsing OMM MarketPrice data from Real-Time - Optimized. The source code and executable files of this example are available in the following directories:

  • Source code files: /opt/lseg/Real-Time-SDK/Cpp-C/Ema/Examples/Training/Consumer/100_Series/113_MP_SessionMgmt
  • Executable file: /opt/lseg/Real-Time-SDK/Cpp-C/Ema/Executables/OL7_64_GCC485/Optimized/


Follow these steps To run the Con113 example:

1. Change the current directory to /opt/lseg/Real-Time-SDK/Cpp-C/Ema/Executables/OL7_64_GCC485/Optimized/

    	
            sh-4.2# cd /opt/lseg/Real-Time-SDK/Cpp-C/Ema/Executables/OL7_64_GCC485/Optimized/
        
        
    

2. Copy the EmaConfig.xml from the EMA directory to the current directory

    	
            sh-4.2# cp /opt/lseg/Real-Time-SDK/Cpp-C/Ema/EmaConfig.xml .
        
        
    

3. Set the LD_LIBRARY_PATH environment variable with the directory path of libcurl.so

    	
            sh-4.2# export LD_LIBRARY_PATH=/opt/lseg/Real-Time-SDK/rtsdk/install/lib64
        
        
    

4. Run the Cons113 example with the following parameters

Connecting to RTO with the V1 authentication

    	
            

sh-4.2# ./Cons113 -username <UserID or MachineID> -password <Password> -clientId <AppKey> -itemName JPY=

loggerMsg

    TimeStamp: 03:34:17.202

    ClientName: ChannelCallbackClient

    Severity: Success

    Text:    Received ChannelUp event on channel Channel_4

        Instance Name Consumer_4_1

        Connected component version: ads3.2.1.L1.linux.tis.rrg 64-bit

loggerMsgEnd

 

RefreshMsg

    streamId="5"

    domain="MarketPrice Domain"

    Solicited

    RefreshComplete

    ClearCache

    state="Open / Ok / None / '*All is well'"

    itemGroup="00 AC"

    permissionData="03 01 01 52 6C"

    qos="RealTime/JustInTimeConflated"

    seqNum="26574"

    name="JPY="

    nameType="1"

    serviceId="257"

    serviceName="ELEKTRON_DD"

    Payload dataType="FieldList"

        FieldList FieldListNum="99" DictionaryId="1"

            FieldEntry fid="1" name="PROD_PERM" dataType="UInt" value="526"

            FieldEntry fid="2" name="RDNDISPLAY" dataType="UInt" value="153"

            FieldEntry fid="3" name="DSPLY_NAME" dataType="Rmtes" value="ASANPAC                                            IFIBK MOW"

            FieldEntry fid="5" name="TIMACT" dataType="Time" value="03:38:00:000                                            :000:000"

            FieldEntry fid="11" name="NETCHNG_1" dataType="Real" value="0.18"

            FieldEntry fid="12" name="HIGH_1" dataType="Real" value="105.19"

            FieldEntry fid="13" name="LOW_1" dataType="Real" value="104.91"

            FieldEntry fid="15" name="CURRENCY" dataType="Enum" value="392"

            FieldEntry fid="17" name="ACTIV_DATE" dataType="Date" value="23 SEP                                             2020"

            FieldEntry fid="19" name="OPEN_PRC" dataType="Real" value="104.92"

            FieldEntry fid="21" name="HST_CLOSE" dataType="Real" value="104.91"

            FieldEntry fid="22" name="BID" dataType="Real" value="105.09"

Connecting to RTO with the V2 authentication

    	
            

sh-4.2# ./Cons113 -clientId <ClientID> -clientSecret <ClientSecret> -itemName JPY=

loggerMsg

    TimeStamp: 03:34:17.202

    ClientName: ChannelCallbackClient

    Severity: Success

    Text:    Received ChannelUp event on channel Channel_4

        Instance Name Consumer_4_1

        Connected component version: ads3.2.1.L1.linux.tis.rrg 64-bit

loggerMsgEnd

 

RefreshMsg

    streamId="5"

    domain="MarketPrice Domain"

    Solicited

    RefreshComplete

    ClearCache

    state="Open / Ok / None / '*All is well'"

    itemGroup="00 AC"

    permissionData="03 01 01 52 6C"

    qos="RealTime/JustInTimeConflated"

    seqNum="26574"

    name="JPY="

    nameType="1"

    serviceId="257"

    serviceName="ELEKTRON_DD"

    Payload dataType="FieldList"

        FieldList FieldListNum="99" DictionaryId="1"

            FieldEntry fid="1" name="PROD_PERM" dataType="UInt" value="526"

            FieldEntry fid="2" name="RDNDISPLAY" dataType="UInt" value="153"

            FieldEntry fid="3" name="DSPLY_NAME" dataType="Rmtes" value="ASANPAC                                            IFIBK MOW"

            FieldEntry fid="5" name="TIMACT" dataType="Time" value="03:38:00:000                                            :000:000"

            FieldEntry fid="11" name="NETCHNG_1" dataType="Real" value="0.18"

            FieldEntry fid="12" name="HIGH_1" dataType="Real" value="105.19"

            FieldEntry fid="13" name="LOW_1" dataType="Real" value="104.91"

            FieldEntry fid="15" name="CURRENCY" dataType="Enum" value="392"

            FieldEntry fid="17" name="ACTIV_DATE" dataType="Date" value="23 SEP                                             2020"

            FieldEntry fid="19" name="OPEN_PRC" dataType="Real" value="104.92"

            FieldEntry fid="21" name="HST_CLOSE" dataType="Real" value="104.91"

            FieldEntry fid="22" name="BID" dataType="Real" value="105.09"

The example will connect to Real-Time - Optimized and subscribe to JPY= from the ELEKTRON_DD service.

Running an ETA example

VAConsumer is an ETA example that uses ValueAdd component to consume data from an OMM Provider, ADS device, OMM Provider application or Real-Time - Optimized. The source code and executable files of this example are available in the following directories:

  • Source code files: /opt/lseg/Real-Time-SDK/Cpp-C/Eta/Applications/Examples/VAConsumer
  • Executable file: /opt/lseg/Real-Time-SDK/Cpp-C/Eta/Executables/OL7_64_GCC485/Optimized

Follow these steps to run the VAConsumer example:

1. Change the current directory to /opt/lseg/Real-Time-SDK/Cpp-C/Eta/Executables/OL7_64_GCC485/Optimized

    	
            sh-4.2# cd /opt/lseg/Real-Time-SDK/Cpp-C/Eta/Executables/OL7_64_GCC485/Optimized
        
        
    

2. Set the LD_LIBRARY_PATH environment variable with the directory path of libcurl.so

    	
            sh-4.2# export LD_LIBRARY_PATH=/opt/lseg/Real-Time-SDK/rtsdk/install/lib64
        
        
    

3. Run the VAConsumer example with the following parameters

Connecting to RTO with the V1 authentication

    	
            

sh-4.2# ./VAConsumer -encryptedSocket ap-southeast-1-aws-3-med.optimized-pricing-api.refinitiv.net:14002 ELEKTRON_DD mp:JPY= -uname <UserID or MachineID>  -passwd <Password> -clientId <AppKey> -sessionMgnt

Connections:
        apac-1-t2.streaming-pricing-api.refinitiv.com:14002 ELEKTRON_DD
                MarketPriceItems: IBM.N
                MarketByOrderItems:
                MarketByPriceItems:
                YieldCurveItems:
                MarketPriceItems (Private Stream):
                MarketByOrderItems (Private Stream):
                MarketByPriceItems (Private Stream):
                YieldCurveItems (Private Stream):
...

Received Source Directory Response:     State: Open/Ok/None - text: ""

Received serviceName: PERM_SVR_SNKDRV

Received serviceName: ELEKTRON_DD

        Service State: Up

Received serviceName: ERT_FD3_LF1


Received Dictionary Response: RWFFld
Field Dictionary complete.

Received Dictionary Response: RWFEnum
Enumerated Types Dictionary complete.

(Channel 9):
JPY=
DOMAIN: RSSL_DMT_MARKET_PRICE
State: Open/Ok/None - text: "*All is well"
        PROD_PERM           526
        RDNDISPLAY          153
        DSPLY_NAME          BARCLAYS     LON
        TIMACT              08:16:00:000:000:000
        NETCHNG_1           -0.25
        HIGH_1              107.30
        LOW_1               106.94
        CURRENCY            JPY(392)
        ACTIV_DATE          15 JUL 2020
        OPEN_PRC            107.22

Connecting to RTO with the V2 authentication

    	
            

sh-4.2# ./VAConsumer -encryptedSocket ap-southeast-1-aws-3-med.optimized-pricing-api.refinitiv.net:14002 ELEKTRON_DD mp:JPY= -clientId <ClientID>  -clientSecret <ClientSecret> -sessionMgnt

Connections:
        apac-1-t2.streaming-pricing-api.refinitiv.com:14002 ELEKTRON_DD
                MarketPriceItems: IBM.N
                MarketByOrderItems:
                MarketByPriceItems:
                YieldCurveItems:
                MarketPriceItems (Private Stream):
                MarketByOrderItems (Private Stream):
                MarketByPriceItems (Private Stream):
                YieldCurveItems (Private Stream):
...

Received Source Directory Response:     State: Open/Ok/None - text: ""

Received serviceName: PERM_SVR_SNKDRV

Received serviceName: ELEKTRON_DD

        Service State: Up

Received serviceName: ERT_FD3_LF1


Received Dictionary Response: RWFFld
Field Dictionary complete.

Received Dictionary Response: RWFEnum
Enumerated Types Dictionary complete.

(Channel 9):
JPY=
DOMAIN: RSSL_DMT_MARKET_PRICE
State: Open/Ok/None - text: "*All is well"
        PROD_PERM           526
        RDNDISPLAY          153
        DSPLY_NAME          BARCLAYS     LON
        TIMACT              08:16:00:000:000:000
        NETCHNG_1           -0.25
        HIGH_1              107.30
        LOW_1               106.94
        CURRENCY            JPY(392)
        ACTIV_DATE          15 JUL 2020
        OPEN_PRC            107.22

The example will connect to Real-Time - Optimized (apac-1-t2.streaming-pricing-api.refinitiv.com:14002) and subscribe to JPY= from the ELEKTRON_DD service.

Modifying an example in the container

This section demonstrates how to modify the 113MarketPriceSessionManagement example by changing the default RIC from IBM.N to JPY= and then re-build the Cons113 example.

1. Change the directory to the 113MarketPriceSessionManagement example

    	
            sh-4.2# cd  /opt/lseg/Real-Time-SDK/Cpp-C/Ema/Examples/Training/Consumer/100_Series/113_MP_SessionMgmt
        
        
    

2. Use a text editor to modify the Consumer.cpp file. In the main function, change the value in the itemName variable from "IBM.N" to "JPY="

    	
            

int main( int argc, char* argv[] )
{
        try {
                AppClient client;
                OmmConsumerConfig config;
                UInt8 userNameSet = 0;
                UInt8 passwordSet = 0;
                UInt8 clientIdSet = 0;

                EmaString itemName = "JPY=";

3. Save changes and then exit the text editor

4. Change the directory to /opt/lseg/Real-Time-SDK/rtsdk/

    	
            sh-4.2# cd /opt/lseg/Real-Time-SDK/rtsdk/
        
        
    

5. Run the make command to rebuild the Cons113 example

    	
            sh-4.2# make Cons113
        
        
    

6. Then, follow steps in the Running an EMA example section to re-run the Cons113 example.

Summary

This article introduces Real-Time SDK and WebSocket API Docker images in Docker Hub. The lsegrealtime/realtimesdk_c docker image contains the latest version of Real-Time C/C++ libraries and examples. The lsegrealtime/realtimesdk_java docker image contains the latest version of Real-Time SDK Java libraries and examples. The lsegrealtime/websocket_api docker image contains WebSocket API Examples used to connect to Real-Time Distribution System or Data Platform to consume real-time data through the WebSocket connections. Then, it demonstrates how to deploy the lsegrealtime/realtimesdk_c docker image on the Docker engines and Azure Containers. Finally, it shows how to run and modify examples to retrieve real-time data from Real-Time – Optimized.

References

  1. Azure.microsoft.com. 2020. Azure Container Instances | Microsoft Azure. [online] Available at: https://azure.microsoft.com/en-us/services/container-instances/ [Accessed 15 July 2020].
  2. Azure.microsoft.com. 2020. Cloud Computing Services | Microsoft Azure. [online] Available at: https://azure.microsoft.com/en-us/ [Accessed 15 July 2020].
  3. Cmake.org. n.d. Cmake. [online] Available at: https://cmake.org/ [Accessed 15 July 2020].
  4. Hub.docker.com. n.d. Docker Image For Real-Time SDK C/CPP. [online] Available at: https://hub.docker.com/repository/docker/lsegrealtime/realtimesdk_c [Accessed 22 Sep 2020].
  5. Hub.docker.com. 2020. Docker Image For Real-Time SDK Java. [online] Available at: https://hub.docker.com/r/lsegrealtime/realtimesdk_java [Accessed 22 Sep 2020].
  6. Hub.docker.com. 2020. Docker Image For Websocket APIs. [online] Available at: https://hub.docker.com/r/lsegrealtime/websocket_api [Accessed 15 July 2020].
  7. Docker Documentation. 2020. Get Docker. [online] Available at: https://docs.docker.com/get-docker/ [Accessed 15 July 2020].
  8. Gradle. 2020. Gradle Build Tool. [online] Available at: https://gradle.org [Accessed 15 July 2020].
  9. Phuriphanvichai, J., 2017. Deploy And Run Real-Time SDK In Docker | DEVELOPER COMMUNITY. [online] Developers.lseg.com. Available at: https://developers.lseg.com/en/article-catalog/article/deploy-and-run-elektron-sdk-docker [Accessed 15 July 2020].
  10. GitHub. n.d. Real-Time-SDK. [online] Available at: https://github.com/Refinitiv/Real-Time-SDK [Accessed 15 July 2020].
  11. GitHub. n.d. Websocket-Api. [online] Available at: https://github.com/Refinitiv/websocket-api/ [Accessed 15 July 2020].
  12. Rungruengrayubkul, V., 2020. Getting Start With Data Platform | DEVELOPER COMMUNITY. [online] Developers.lseg.com. Available at: https://developers.lseg.com/en/article-catalog/article/getting-start-with-refinitiv-data-platform [Accessed 15 July 2020].