Adaptive Communication Environment

Werbung
Adaptive
Communication
Environment
Teil 1
Gliederung
Motivation
 Überblick ACE

 Entwurfsmuster,
Framework
Wrapper Facade
 Architektur ACE
 Bsp. Interprozesskommunikation mit ACE

Motivation


Gängige Anforderungen an Software
 Erweiterbar
 Zuverlässig
 Flexibel
 Wiederverwendbar
 Portierbar
 Finanzierbar
Schwer realisierbar, falls
 Kernkonzepte
& Softwarekomponenten
ständig neu “erfunden”
 Monolithischer Softwareaufbau
Motivation

Entwicklung von Multi PlattformAnwendungen problematisch:
 Komponentenbibliotheken
mit verschiedenen
API‘s und Semantik auf unterschiedlichen
Plattformen
 Verschiedene Standards: z.B. POSIX,
UNIX98, Win32
Beispiel Sockets API



Fehleranfällig:
 Häufig Return-Werte ignoriert
 Netzwerk Byte-Ordering
vergessen
Nicht portabel:
 Headerfiles
 Unterschiedliche Standards
In C geschrieben
→ C++ Wrapper wünschenswert
#include <sys/types.h>
#include <sys/socket.h>
int echo_server () {
…
int n_handle;
int s_handle = socket (PFJJNIX, SOCK_DGRAM, 0);
…
addr.sin_family = AF_INET;
addr.sin_port = PORT_NUM;
…
if (bind (s_handle, (struct sockaddr *) &addr,
sizeof addr) == -1)
return -1;
if (n_handle = accept (s_handle, (struct sockaddr *) &addr,
&addr_len) != -1) {
int n;
while ((n = read (s_handle, buf, sizeof buf}) > 0)
write (n_handle, buf, n);
close (n_handle); }
return 0;
}
Überblick ACE



Open Source Software Toolkit
OO-Framework zur Entwicklung von
Kommunikationssystemen auf verschiedenen
Plattformen
Abgedeckte Aspekte:
 Verbindungsaufbau und Diensteinitialisierung
 Event demultiplexing & Event handler dispatching
 Statische und dynamische Dienstekonfiguration
 Nebenläufigkeit und Synchronisierung
 Verteilte Kommunikationsdienste (Namen, Zeit,
Loggen, ...)
Überblick ACE



Entwickelt u.a. von Douglas Schmidt
1992 als open source Projekt veröffentlicht
Ab 1994 Einsatz in kommerziellen Produkten
 Boeing
 Siemens
 Ericson
 Nokia
 http://www.cs.wustl.edu/~schmidt/ACE-users.html

Firma: Riverace (www.riverace.com)
Überblick ACE

Unterstützte Plattformen
 Alle
Windows Versionen
 Unix, Linux (SunOS 4.x, HP UX, Linux Redhat,
Suse etc.)
 Echtzeit Betriebsysteme (VxWorks, Chorus ,...)
 Diverse Großrechner Architekturen
 Auf vielen c++ Compilern getestet
ACE - Musterübersicht

ACE implementiert
komplexe
Entwurfsmuster
und Frameworks

Exemplarisch
 Double
Checked
Pattern im Kontext
“Singleton Pattern”
Bsp. Singleton

Zweck



Existenz max. einer Instanz einer Klasse
Globaler Zugriffspunkt auf Instanz
Struktur
Singleton
static instance() ○
getData()
static instance_
data_
return instance_
Bsp. Singleton

Eigene Implementierung, Versuch 1
1
2
3
4
5
6
7

public class Singleton{
private static instance_
= new Singleton();
public static instance(){
return instance_;
}
}
Probleme: impliziter Konstruktor, Instanz wird
manchmal unnötig erzeugt
Bsp. Singleton

Eigene Implementierung, Versuch 2
1
2

public class Singleton{
private static instance_;
3
private Singleton(){};
4
5
6
public static instance(){
if (instance_ == 0)
instance_ = new Singleton();
7
8
9
return instance_;
}
}
Problem: fehlende Synchronisierung in Zeilen 5-6
Bsp. Singleton

Eigene Implementierung, Versuch 3
1

public class Singleton{
... // Korrekt
2
3
4
5
6
public static instance(){
if (instance_ == 0)
synchronized {
instance_ = new Singleton();
}
7
8
9
return instance_;
}
}
Problem: falsche Synchronisierung
Bsp. Singleton

Korrekte Lösung dokumentiert im “Double
Check Pattern”
1
2
3
4
5
6
if (instance_ == 0){
synchronized {
if (instance_ == 0)
instance_ = new Singleton();
}
}
Muster

Jedes Muster beschreibt ein in unserer Umwelt
beständig wiederkehrendes Problem und erläutert den
Kern der Lösung für dieses Problem, so dass Sie diese
Lösung beliebig oft anwenden können, ohne sie jemals
ein zweites Mal gleich auszuführen
(Christopher Alexander)

Formuliert für architektonische Probleme
Idee übertragbar auf Entwurf von Softwaresystemen

Muster

Unterschiedliche Ebenen von Mustern:
 Architekturmuster beschreibt Organisationsstruktur
(Subsysteme, Komponenten)
 Entwurfsmuster beschreibt Struktur und Beziehungen
innerhalb eines Subsystems
 Idiom beschreibt Lösung eines Implementierungsproblems in
einer bestimmten Programmiersprache
Entwurfsmuster





Beschreiben abstrakt & strukturiert oft
vorkommende Probleme & ihre Lösungen
Erfassen Entwurfsentscheidungen, die
erfahrungsgemäß gut funktionieren
Müssen an konkrete Probleme angepasst
werden
Weitgehend unabhängig von spezifischen
Programmiersprachen
Formen Sprache, um Entwürfe zu diskutieren
Entwurfsmuster - Bestandteile
Name und Klassifikation
 Zweck
 Auch bekannt als
 Motivation
 Anwendbarkeit
 Struktur
 Teilnehmer

Entwurfsmuster - Bestandteile
Zusammenarbeit
 Konsequenzen
 Implementierung
 Beispielcode
 Bekannte Anwendungen
 Verwandte Muster

Entwurfsmuster - Vorteile
Zuverlässig
 Wiederverwendbar
 Erweiterbar
 Vereinfachen Kommunikation
(Standardisierung von Namen…)

Framework





Implementation von Entwurfsmustern
Repräsentiert durch Menge von abstrakten Klassen und
Art und Weise wie Instanzen zusammenarbeiten
Wiederverwendbares Design für Anwendung
Definiert grundlegende Struktur und Architektur der
Anwendung
Unterschied zu Klassenbibliothek:


Hauptprogramm für globale Steuerung
Inversion of Control
Portabler Code

Möglichkeiten:

#ifdefs
#if defined (_WIN32)
SOCKET h;
#else
int h;
#endif
→komplex, schwer wartbar/erweiterbar
 Musterbasiert:
Wrapper Facade →
Verschleiern von plattformspezifischem Code
Wrapper Facade

Besteht aus einer oder mehreren Klassen, die Funktionen und
Datenstrukturen (die z.B. von nichtobjektorientierten API‘s
bereitgestellt werden) innerhalb portabler, objektorientierter
Interfaces kapseln
Wrapper Facade – Implementation

Semantisch zusammengehörende Funktionen
identifizieren und in Wrapper Facade Klassen
gruppieren

Mehrere Funktionen in einer Methode vereinigen
Socket API:
ACE_SOCK_Acceptor:
…
int n_handle;
s_handle=socket(…);
…
bind(…);
listen(…);
n_handle=accept(s_handle,…);
ACE_SOCK_Acceptor acceptor;
…
acceptor.open (…);
acceptor.accept(…);
Wrapper Facade – Implementation

Funktionen unter Wrapper Facade vereinigen
um damit Portabilität zu gewährleisten
Bsp. Thread Management
Win32: CreateThread()
POSIX: pthread_create()
UI:
thr_create()
Unterschiedliche Rückgabewerte
ACE_Thread_Manager::spawn()
Benötigte Informationen über Argumente
übergeben
1 Rückgabekonvention: 0 erfolgreich, -1
Fehler (Fehlergrund in errno gespeichert)
Wrapper Facade ACE_Thread_Manager::spawn()
1.
ACE_Thread_Manager::spawn (run_svc, thread_args, THR DETACHED 1 THR
SCOPE SYSTEM);
3.
//zugrundeliegende Plattform, hier: UI Threads
thr_create (0, 0, run_svc, thread_args, THRJ3ETACHED | THR_SCOPE_SYSTBM, &thread_id);
5.
run_svc (thread_args) {/*...*/}
1. Betriebssystem erzeugt Thread Ausführungskontext
2. Betriebssystem allokiert Speicher für Thread Stack
3. Register Set des neuen Thread wird vorbereitet, ruft bei
Ausführung run_svc() auf
4. Thread als ausführbar markiert, Betriebssystem kann ihn
ausführen
ACE Architektur
ACE Architektur

Adaption Layer:
 Ca.
10 % von ACE
 Zwischen eigentlichen Betriebssystem API‘s und Rest
von ACE
 Kapselt grundlegende OS Mechanismen mittels
Wrapper Facade → einheitliches Interface für
betriebsystemnahe Aufrufe
 Implementiert in ACE_OS Klasse (ca. 500 statische C
Methoden)
ACE Architektur - Adaption Layer

Kapselt u.a. folgende OS Mechanismen:
 Multi-threading
und Synchronization
 Interprozesskommunikation
 Event demultiplexing
 Dynamisches Linking
 Memory Mapping und shared memory
ACE Architektur

OO-Wrapper Layer
 Ca.
50 %
 Verwendet Wrapper Facade Pattern
 Bietet praktisch selbe Funktionalität wie Adaption
Layer, verwendet allerdings objektorientierte,
typsichere C++ Klassen, die ACE_OS Methoden
aufrufen
 Applikationen verwenden Wrapper Klassen durch
Vererbung oder Instantiierung
ACE Architektur - OO-Wrapper Layer

Nebenläufigkeit und Synchronisation
ACE_Mutex, ACE_Token, …

Prozess-/Threadmanagement
ACE_Process, ACE_Thread_Manager, …

Interprozesskommunikation
IPC SAP

Memory Management
ACE_Allocator, ACE_Malloc, …

Timer Klassen
ACE_Timer_Queue, …

Signal Handling
ACE_Sig_Handler, …
ACE Architektur

Framework Layer
 Highest
level Building Blocks in ACE
 Integriert und vergrößert Wrapper Klassen
 Framework Komponenten basieren auf
Entwurfsmustern spezifisch für
Kommunikationssoftware
ACE Architektur – Framework Layer

Event handling framework
 Reactor/Proactor
überwachen mehrere Event-Quellen

Verbindungs- und Serviceinitialisierung
 Acceptor/Connector
passiver/aktiver Verbindungsaufbau, Svc_Handler verarbeitet
eigentliche Ereignisse


Stream Framework
Service Configuration Framework
 Service Configurator
unterstützt dynamische Initialisierung, Unterbrechung,
Wiederaufnahme, Rekonfiguration und Beendigung von Diensten
ACE Architektur

Service and Components Layer
 Fertige
Anwendungen, die auf ACE basieren,
u.a.:
Distributed logging service
 Webserver JAWS
 Corba-Implementierung TAO

Beispiel: IPC_SAP
ACE_IPC_SAP
ACE_SOCK
…
ACE_TLI
…
ACE_SPIPE
…
ACE_FIFO
…
ACE_SOCK - Wrapper für BSD Sockets

ACE_SOCK_Acceptor
passiver Verbindungsaufbau, basierend auf accept() und listen()

ACE_SOCK_Connector
aktiver Verbindungsaufbau, basierend auf connect()

ACE_SOCK_Dgram
kapselt UDP Protokoll-Funktionalität

ACE_SOCK_IO
kapselt u.a. send(), receive(), write()

ACE_SOCK_Stream
kapselt TCP Protokoll-Funktionalität, nach Verbindungsaufbau verwendet
Beispiel: passiver Server
#include "ace/SOCK_Acceptor.h"
#include "ace/SOCK_Stream.h"
…
class Server{
public:
Server (int port):
server_addr_(port),peer_acceptor_(server_addr_) {
data_buf_= new char[SIZE_BUF]; }
int accept_connections ()
{
if (peer_acceptor_.get_local_addr (server_addr_) == -1)
ACE_ERROR_RETURN ((LM_ERROR,"%p\n","Error in get_local_addr"),1);
ACE_DEBUG ((LM_DEBUG,"Starting server at port %d\n",
server_addr_.get_port_number ()));
while(1){
ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT);
if (peer_acceptor_.accept (new_stream_, &client_addr_, &timeout)== -1)
{
ACE_ERROR ((LM_ERROR, "%p\n", "accept"));
continue; }
else {
ACE_DEBUG((LM_DEBUG,
"Connection established with remote %s:%d\n",
client_addr_.get_host_name(),client_addr_.get_port_number()))
handle_connection(); }
}}
int handle_connection()
{
for(int i=0;i<NO_ITERATIONS;i++) {
int byte_count=0;
if( (byte_count=new_stream_.recv_n (data_buf_, SIZE_DATA, 0))==-1)
ACE_ERROR ((LM_ERROR, "%p\n", "Error in recv"));
else{
data_buf_[byte_count]=0;
ACE_DEBUG((LM_DEBUG,"Server received %s \n",data_buf_));
} }
if (new_stream_.close () == -1)
ACE_ERROR ((LM_ERROR, "%p\n", "close"));
return 0; }
private:
char *data_buf_;
ACE_INET_Addr server_addr_;
ACE_INET_Addr client_addr_;
ACE_SOCK_Acceptor peer_acceptor_;
ACE_SOCK_Stream new_stream_;
};
int main (int argc, char *argv[])
{
if(argc<2){
ACE_ERROR((LM_ERROR,"Usage %s <port_num>", argv[0]));
ACE_OS::exit(1); }
Server server(ACE_OS::atoi(argv[1]));
server.accept_connections(); }
Beispiel: Connector in Verbindung mit Acceptor
#include "ace/SOCK_Connector.h"
#include "ace/INET_Addr.h"
…
class Client{
public:
Client(char *hostname, int port):remote_addr_(port,hostname)
{
data_buf_="Hello from Client";
}
int connect_to_server()
{
ACE_DEBUG ((LM_DEBUG, "(%P|%t) Starting connect to %s:%d\n",
remote_addr_.get_host_name(),remote_addr_.get_port_number()));
if (connector_.connect (client_stream_, remote_addr_) == -1)
ACE_ERROR_RETURN ((LM_ERROR,"(%P|%t) %p\n","connection failed"),-1);
else
ACE_DEBUG ((LM_DEBUG,"(%P|%t) connected to %s\n",
remote_addr_.get_host_name ()));
return 0;
}
int send_to_server()
{
for(int i=0;i<NO_ITERATIONS; i++){
if (client_stream_.send_n (data_buf_, ACE_OS::strlen(data_buf_)+1, 0) == -1){
ACE_ERROR_RETURN ((LM_ERROR,"(%P|%t) %p\n","send_n"),0);
break;
}}
close();
}
int close()
{
if (client_stream_.close () == -1)
ACE_ERROR_RETURN ((LM_ERROR,"(%P|%t) %p\n","close"),-1);
else
return 0;
}
private:
ACE_SOCK_Stream client_stream_;
ACE_INET_Addr remote_addr_;
ACE_SOCK_Connector connector_;
char *data_buf_;
};
int main (int argc, char *argv[])
{
...
Client client(argv[1],ACE_OS::atoi(argv[2]));
client.connect_to_server();
client.send_to_server(); }
Fazit
+ plattformunabhängig
+ vielseitig anwendbar
+ gut dokumentiert



Huston, Johnson, Syyid: The ACE Programmers Guide
Schmidt, Huston: C++ Network Programming. Volume 1+2
http://www.cs.wustl.edu/adaptive.html
- Keine Exceptions, nur Fehlercodes


1992 beinhaltete C++ Standard Exceptions noch nicht hinreichend
Exceptions unter Performance Gesichtspunkten eher nachteilig
Zugehörige Unterlagen
Herunterladen