Data Distribution ServiceIl Data Distribution Service for Real Time Systems (DDS) è uno standard emanato dall'Object Management Group (OMG) che definisce un middleware per la distribuzione di dati in tempo reale secondo il paradigma publish/subscribe. IntroduzioneIl DDS è un middleware per sistemi incentrati sui dati (dall'anglosassone data-centric systems), ovvero sistemi distribuiti il cui funzionamento è basato sullo scambio di dati in tempo reale da più sorgenti a più destinazioni. Esempi tipici sono i sistemi di controllo, i sistemi di difesa, i sistemi di trading finanziario, ecc. I vantaggi dell'uso di DDS in questo dominio sono i seguenti: ![]()
Grazie a queste caratteristiche, DDS sta rapidamente guadagnando terreno nel mercato dei middleware per sistemi distribuiti in tempo reale, soprattutto nel dominio delle applicazioni militari e del controllo del traffico aereo. Storia dello standardLo standard DDS è stato emanato da OMG sotto la spinta di due produttori, la californiana Real Time Innovations ed il gruppo francese Thales, che hanno sviluppato rispettivamente NDDS e SPLICE per lo stesso settore di mercato. La specifica DDS 1.0 ha così uniformato l'interfaccia di programmazione di questi due prodotti ed ha contribuito alla nascita di ulteriori implementazioni, come OpenDDS di Object Computing, Inc. (OCI), basata su TAO e quindi open source. Con la specifica DDS 1.1 (datata dicembre 2005) vengono aggiunte allo standard una serie di specifiche da rispettare per garantire l'interoperabilità tra le diverse implementazioni. La versione corrente dello standard è DDS 1.2 ed è stata approvata nel gennaio 2007. Il DDS SIG di OMG sta ora lavorando alla versione DDS 1.3. Architettura![]() Il Data Distribution Service è concepito come una soluzione infrastrutturale alla programmazione di applicazioni incentrate sui dati. Il suo scopo è di nascondere interamente le problematiche della gestione della comunicazione nella programmazione di applicazioni data-centric. Lo standard è rappresentato da una serie di API suddivise in due livelli:
Entità DCPS![]() IN DCPS sono definite le seguenti entità:
Qualità del ServizioData Distribution Service offre una vasta gamma di parametri relativi alla qualità di servizio, impostabili sulla base della singola entità coinvolta nella comunicazione. Questa scelta di progetto fa di DDS l'unico standard attualmente disponibile per la comunicazione publish/subscribe in tempo reale. I parametri relativi alla qualità del servizio in DDS possono essere suddivisi in tre grandi categorie:
In base a questa classificazione vengono di seguito elencati i parametri di maggiore rilevanza concettuale, indicando le entità alle quali il parametro si riferisce. Affidabilità della comunicazione
Esempi d'usoNei seguenti esempi il publisher pubblica dati relativi al topic "Example HelloWorld" ad intervallo di un secondo. Dall'altro lato il subscriber preleva i dati non appena questi vengono ricevuti e li stampa a video. Il tipo di dato associato al topic "Example HelloWorld" è definito attraverso il linguaggio IDL nel seguente modo: struct HelloWorld {
string name<64>;
string msg<256>;
}
La specifica IDL viene poi tradotta nel linguaggio utilizzato per lo sviluppo dell'applicazione. In C e C++ darà luogo ad una struttura del tipo: struct HelloWorld {
char* name;
char* msg;
}
mentre in Java si avrà la seguente classe: public class HelloWorld {
public String name;
public String msg;
}
Dal tipo IDL vengono anche generate le interfacce tipizzate per la lettura e la scrittura di dati sul topic, ovvero HelloWorldDataReader ed HelloWorldDataWriter. Per semplicità di trattazione, nei seguenti esempi si utilizzano per ogni entità le politiche di QoS di default. Per approfondimenti riguardo alla parametrizzazione della QoS si faccia riferimento allo standard. C++Publisher Side#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> // needed for sleep()
#include <dds_cpp.h>
using DDS;
int main(int argc, char *argv[])
{
int domainId = 0;
int sample_count = 100;
DomainParticipant *participant = NULL;
Publisher *publisher = NULL;
Topic *topic = NULL;
DataWriter *writer = NULL;
HelloWorldDataWriter *helloWriter = NULL;
HelloWorld instance;
InstanceHandle_t instance_handle = HANDLE_NIL;
const char *type_name = NULL;
int count = 0;
participant = TheParticipantFactory->create_participant(
domainId, PARTICIPANT_QOS_DEFAULT, NULL /* listener */,
STATUS_MASK_NONE);
publisher = participant->create_publisher(
PUBLISHER_QOS_DEFAULT, NULL /* listener */,
STATUS_MASK_NONE);
type_name = HelloWorldTypeSupport::get_type_name();
HelloWorldTypeSupport::register_type(
participant, type_name);
topic = participant->create_topic(
"Example HelloWorld",
type_name, TOPIC_QOS_DEFAULT, NULL /* listener */,
STATUS_MASK_NONE);
writer = publisher->create_datawriter(
topic, DATAWRITER_QOS_DEFAULT, NULL /* listener */,
STATUS_MASK_NONE);
helloWriter = HelloWorldDataWriter::narrow(writer);
strcpy(instance.name, "MyName");
instance_handle = HelloWorld_writer->register_instance(instance);
/* Main loop */
for (count=0; (sample_count == 0) || (count < sample_count); ++count) {
sprintf(instance.msg, "Hello World! (count %d)", count);
printf("Writing: %s", instance.msg);
helloWriter->write(*instance, instance_handle);
sleep(1);
}
participant->delete_contained_entities();
TheParticipantFactory->delete_participant(participant);
}
Subscriber side#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> // needed for sleep()
#include <dds_cpp.h>
using DDS;
/* Listener used to receive notifications on data updates */
class HelloWorldListener : public DataReaderListener {
public:
virtual void on_data_available(DataReader* reader);
};
void HelloWorldListener::on_data_available(DataReader* reader)
{
HelloWorldDataReader *HelloWorld_reader = NULL;
HelloWorldSeq data_seq;
SampleInfoSeq info_seq;
HelloWorld_reader = HelloWorldDataReader::narrow(reader);
retcode = HelloWorld_reader->take(
data_seq, info_seq, LENGTH_UNLIMITED,
ANY_SAMPLE_STATE, ANY_VIEW_STATE, ANY_INSTANCE_STATE);
for (i = 0; i < data_seq.length(); ++i) {
if (info_seq[i].valid_data) {
printf("From %s: %s\n", data_seq[i].name, data_seq[i].msg);
}
}
retcode = HelloWorld_reader->return_loan(data_seq, info_seq);
}
int main(int argc, char *argv[])
{
int domainId = 0;
DomainParticipant *participant = NULL;
Subscriber *subscriber = NULL;
Topic *topic = NULL;
HelloWorldListener *reader_listener = NULL;
DataReader *reader = NULL;
ReturnCode_t retcode;
const char *type_name = NULL;
participant = TheParticipantFactory->create_participant(
domainId, participant_qos, NULL /* listener */, STATUS_MASK_NONE);
subscriber = participant->create_subscriber(
SUBSCRIBER_QOS_DEFAULT, NULL /* listener */, STATUS_MASK_NONE);
type_name = HelloWorldTypeSupport::get_type_name();
retcode = HelloWorldTypeSupport::register_type(
participant, type_name);
topic = participant->create_topic(
"Example HelloWorld",
type_name, TOPIC_QOS_DEFAULT, NULL /* listener */,
STATUS_MASK_NONE);
/* Create data reader listener */
reader_listener = new HelloWorldListener();
reader = subscriber->create_datareader(
topic, DATAREADER_QOS_DEFAULT, reader_listener,
STATUS_MASK_ALL);
/* Main loop. Does nothing. Action taken in listener */
for (count=0; (sample_count == 0) || (count < sample_count); ++count) {
printf("HelloWorld subscriber sleeping for %d sec...\n",
receive_period.sec);
sleep(10);
}
participant->delete_contained_entities();
TheParticipantFactory->delete_participant(participant);
}
Altri progetti
Collegamenti esterni
|
Portal di Ensiklopedia Dunia