
Table of Contents Object-Oriented Network Overview Programming with C++ { Recognizing patterns { Typ es of patterns Design Patterns for Initializing Passively initiali zi ng network services Network Services in OO { Overview of tactical patterns Communication Frameworks { Overview of strategic patterns Implementing the Acceptor pattern Douglas C. Schmidt { First implementation [email protected] u { Revised implementation Washington University Summary 2 1 Identifying Common Behavior and Structure Intro duction \Pattern recognition" o ccurs by observing Design patterns capture successful solutions recurring solution strategies to recurring problems that arise during soft- ware development e.g., network servers often lo ok as follows: Useful design patterns and design pattern void do_server void { descriptions, like useful software, evolve over listener_handle.initialize ; time for ;; { { Likewise, patterns build up on other patterns to // Create service to handle connection. form families of related patterns service = new Service; // Wait for and accept connection. client_handle = listener_handle.accept ; The following material captures the evolu- // Activate service. tion of design patterns that are useful for service->open client_handle; managing the lifecycle of services in OO // Perform service. communication software service->run ; } } 3 4 Identifying Limitations with the Strategic and Tactical Patterns Existing Solution Strategic design patterns have an extensive impact on the software architecture The solution ab ove is limit ed by tightly cou- pling: { Typically oriented to solutions in aparticular do- main { Choice of IPC mechanisms { Connection and service handling strategies { e.g., Reactor and Acceptor pattern in the domain of event-driven, connection-oriented communica- { Choice of demultiplexing strategy tion software { Choice of advertisement strategy { Choice of endp oint listening strategy Tactical design patterns have a relatively lo- calized impact on a software architecture { Choice of service creation strategy { Typically domain-indep endent { Choice of connection acceptance strategy { e.g.,Wrapp er, Adapter, Bridge, Factory Metho d, { Choice of service concurrency strategy and Strategy Strategic and tactical design patterns re- It is imp ortant to understand b oth typ es of move these limitati ons and decrease cou- patterns pling 6 5 Decoupling IPC Mechanisms Problem The Wrapp er Pattern { IPC mechanisms likesockets, TLI, and STREAM pip es have non-uniform interfaces, even though they b ehavior similarly Intent { Encapsulate lower-level functions within typ e-safe, mo dular, and p ortable class interfaces Key forces { Many IPC mechanisms or subsets of mechanisms provide logically equivalent services even though This pattern resolves the following force that their interfaces are physically di erent arises when using native C-level OS APIs . e.g., TLI vs. so ckets 1. How to avoid tedious, error-prone, and non-p ortable programming of low-level IPC mechanisms { Many IPC mechanisms are written in low-level C co de 2. How to combine multiple related, but indep endent, functions into a single cohesive abstraction Solution { Use the Wrapp er and Adapter patterns 7 8 Structure of the Wrapp er Pattern The Adapter Pattern Intent 1: request () Wrapper Convert the interface of a class into another inter- client { request() face client exp ects . Adapter lets classes work together that couldn't otherwise b ecause of incompatible interfaces 2: specific_request() This pattern resolves the following force that rises when using conventional OS inter- Wrappee a faces specific_request() 1. `How to provide an interface that expresses the similarities of seemingly di erent OS mechanisms such as networking or lo cking 9 10 Decoupling Demultip lexi ng Strategy Structure of the Adapter Pattern Problem Servers often must handle events from more than 1: request () { Target one source client request() = 0 A Key forces { It is inecient to rep eatedly \p oll" each event source and it is incorrect to blo ck inde nitely on Adapter Adaptee any one source of events specific_request() request() 2: specific_request() { Extensibility is limited if the demultiplexing co de is coupled with the application event handling co de Solution { Use the Reactor pattern 12 11 Structure The Reactor Pattern select (handles) Concrete foreach h in handles loop APPLICATION Event Intent h->handle_event (type) APPLICATION end loop Handler Decouple event demultiplexing and event handler { - SPECIFIC - rmed in resp onse dispatching from the services p erfo INDEPENDENT to events Reactor handle_events() 1 n register_handler(eh, type) This pattern resolves the following forces r event-driven software: fo remove_handler(eh, type) Event Handler 1 1 handle_event(type) How to demultiplex multiple typ es of events from 1. 1 multiple sources of events eciently within a single get_handle() thread of control n Handles A 2. How to extend application b ehavior without requir- ing changes to the event demultiplexing/dispatching framework Participants in the Reactor pattern 14 13 Collab oratio ns Decoupling Connection and Handling Strategies callback : Service main Concrete reactor program Event_Handler : Reactor Problem Reactor() INITIALIZE register_handler(callback) Coupling initialization strategies with the service REGISTER HANDLER { MODE es it hard to change either one with- get_handle() handling mak EXTRACT HANDLE handle_events() out a ecting the other INITIALIZATION START EVENT LOOP select() FOREACH EVENT DO handle_event() Key forces EVENT OCCURS MODE EVENT Services tend to change more often than connec- REMOVE HANDLER handle_close() { HANDLING tion establishment strategies Solution Dynamic interaction among participants in { Use the Acceptor pattern the Reactor pattern 16 15 The Acceptor Pattern Intent Structure of the Acceptor Pattern { Decouple the passive initialization of a service from the tasks p erformed once the service is initialized Svc Handler This pattern resolves the following forces Svc Handler Acceptor r network servers using interfaces like so ck- fo peer_stream_ or TLI: ets peer_acceptor_ open() ACTIVATES handle_event() 1. How to reuse passive connection establishment co de for each new service Reactor 2. How to make the connection establishment co de rtable across platforms that may contain di er- po handle_event() ent IPC mechanisms 3. How to ensure that a passive-mo de descriptor is not accidentally used to read or write data 4. How to enable exible strategies for creation, con- nection establishment, and concurrency 18 17 Structure of the First Acceptor Pattern Implementati on First Implementati on of the Concrete_Svc_Handler SOCK Stream n SOCK_Acceptor r Pattern Accepto 1 Concrete Concrete Svc Handler Acceptor LAYER LAYER The following slides illustrate an implemen- ACTIVATES APPLICATION APPLICATION tation of the Acceptor pattern { This solution relies up on an implementation of the PEER_STREAM r pattern, as well as the Adapter pattern Reacto Svc SVC_HANDLER A PEER_ACCEPTOR Handler Acceptor A open() handle_event() Subsequent slides will describ e limitati ons LAYER LAYER CONNECTION CONNECTION with this rst approach sh = new SVC_HANDLER; peer_acceptor.accept(*sh); reactor->register_handler (sh); Other tactical patterns will be used to re- Event these limitati ons move Handler 1 Reactor LAYER LAYER handle_event() n REACTIVE REACTIVE 19 20 Typical Acceptor Use-Case Acceptor Class Interface SERVER A factory for initial i zi ng network services LOGGING : Logging passively DAEMON Acceptor <class SVC_HANDLER, // Type of service template : Logging PEER_ACCEPTOR> // Accepts connections class Handler class Acceptor : public Event_Handler { public: : Logging Initialize and register with Reactor. // Handler : Reactor virtual int open const PEER_ACCEPTOR::PEER_ADDR &, Reactor *; // Creates, accepts, and activates SVC_HANDLER's. LOGGING virtual int handle_event HANDLE; RECORDS Demultiplexing hooks. // LOGGING CONNECTION SERVER HANDLE get_handle void const; virtual RECORDS REQUEST CLIENT private: // Passive connection mechanism. EPTOR peer_acceptor_; PEER_ACC CLIENT CLIENT // Event demultiplexor. Reactor *reactor_; }; 22 21 Acceptor Use-case Co de Distributed logging server Acceptor Class Implementation // Shorthand names. class Logging_Handler : define SH SVC_HANDLER public Svc_Handler<SOCK_Stream> define PR_AC PEER_ACCEPTOR { public: // Initialize the Acceptor // Obtain HANDLE. virtual HANDLE get_handle void const; template <class SH, class PR_AC> int Acceptor<SH, PR_AC>::open const PR_AC::ADDR &l_addr, // Called back to process logging records. Reactor *reactor virtual int handle_event HANDLE; { }; this->reactor_ = reactor; typedef Acceptor<Logging_Handler, SOCK_Acceptor> // Forward to PEER_ACCEPTOR to advertise endpoint. Logging_Acceptor; this->peer_acceptor_.open l_addr; int main void { // Register with Reactor to listen for connections. Reactor reactor; Logging_Acceptor acceptor; this->reactor_->register_handler this, READ_MASK; acceptor.open LOGGER_PORT, &reactor; } for ;; reactor.handle_events ; } 23 24 Collab orati on in the Acceptor Pattern acc : Server sh: reactor : Acceptor Svc_Handler Reactor Factory that create, connects, and activates new // open() INITIALIZE single-threaded SVC_HANDLER objects. // register_handler(acc) REGISTER HANDLER get_handle() <class SH, class PR_AC> int template EXTRACT HANDLE <SH, PR_AC>::handle_event HANDLE Acceptor handle_events() PHASE START EVENT LOOP ENDPOINT { FOREACH
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages16 Page
-
File Size-