home/ []schmidt/pdf/ace-examples4.pdf · rds," i.e., so ck ets and tli, mak es po rtabilit y...
TRANSCRIPT
Developing E�cient and Portable
Communication Software with ACE and C++
Chris Gill and Douglas C. Schmidt
Distributed Object Computing Group
Computer Science Department, Washington University, St. Louis
http://www.cs.wustl.edu/�schmidt/ACE-examples4.ps.gz
ACE C++ Wrapper TutorialProblem: Software Evolution
DDIIAAGGNNOOSSTTIICC
SSTTAATTIIOONNSS
AATTMMMMAANN
AATTMMLLAANN
AATTMMLLAANN
MMOODDAALLIITTIIEESS
((CCTT,, MMRR,, CCRR)) CCEENNTTRRAALL
IIMMAAGGEESSTTOORREE
CCLLUUSSTTEERRIIMMAAGGEESSTTOORREE
DDXXIIMMAAGGEESSTTOORREE
� Key Challenges
{ Communication software
evolves over time
� Requirements change
� Platforms change
� New design forces emerge
{ It is essential to plan for
inevitable change
1
ACE C++ Wrapper Tutorial
Solution: Plan for Change Using Frameworks and
Patterns
Framework Framework
Tilde
FrameworkCached VirtualFilesystem
StrategyProtocol PipelineConcurrency
Expander
I/O Strategy
~/home/...
Mem
ento
Reactor/Proactor Strategy Singleton
Sta
teS
ervi
ce C
on
fig
ura
tor
Sta
te
StrategyActive ObjectPipes and Filters
Ad
apter
Service Configurator
ProtocolHandler
ProtocolFilter
Accep
tor
Event Dispatcher
Asynchronous Completion Token
� Solution Approach
{ Identify sources of
commonality and
variability
{ Use patterns to
identify reusable
design artifacts
{ Use frameworks to
\unify" variation in
code artifacts
2
ACE C++ Wrapper Tutorial
Sources of Variation in Communication Software
WIDE AREA
NETWORK
SATELLITESSATELLITESTRACKINGTRACKINGSTATIONSTATION
PEERSPEERS
STATUS INFO
COMMANDS BULK DATA
TRANSFER
LOCAL AREA NETWORK
GROUNDSTATION
PEERS
GATEWAY
� Syntactic Variations
{ Unsupported non-essential APIs
{ Gratuitous di�erences in API
� Semantic Variations
{ Underlying platform di�erences
{ Framework must respect these
di�erences
� Complex Variations
{ Unsupported essential portions
of API
{ Emulation is necessary
3
ACE C++ Wrapper Tutorial
ACE framework: Resolving Syntactic Variations
int ACE_OS::fstat (ACE_HANDLE handle,
struct stat *stp)
{#if defined (ACE_PSOS_LACKS_PHILE)
ACE_UNUSED_ARG (handle);
ACE_UNUSED_ARG (stp);
ACE_NOTSUP_RETURN (-1);
#elif defined (ACE_PSOS)
ACE_OSCALL_RETURN
(::fstat_f (handle, stp), int, -1);
#elseACE_OSCALL_RETURN
(::fstat (handle, stp), int, -1);
#endif /* ACE_PSOS_LACKS_PHILE */
}
� Examples
{ Unsupported
� Provide \no-op"
de�nitions
� Conditional compilation
{ Syntax
� Re-map function
parameters
4
ACE C++ Wrapper Tutorial
ACE framework: Resolving Semantic Variations
int ACE_OS::clock_gettime
(clockid_t clockid, struct timespec *ts)
{#if defined (ACE_HAS_CLOCK_GETTIME)
ACE_OSCALL_RETURN (::clock_gettime
(clockid, ts), int, -1);
#elif defined (ACE_PSOS)
ACE_UNUSED_ARG (clockid);
ACE_PSOS_Time_t pt;
int result = ACE_PSOS_Time_t::get_system_time (pt);
*ts = ACE_static_cast (struct timespec, pt);
return result;
#elseACE_UNUSED_ARG (clockid);
ACE_UNUSED_ARG (ts);
ACE_NOTSUP_RETURN (-1);
#endif /* ACE_HAS_CLOCK_GETTIME */
}
� Examples
{ Underlying di�erences
� Time in clock ticks
� Ticks-per-second is
board-dependent
{ Framework must respect
these di�erences
� Provide a consistent
abstraction
� Intermediate wrappers
are useful for small,
coherent abstractions
5
ACE C++ Wrapper Tutorial
ACE framework: Resolving Complex Variations
void *ACE_TSS_Emulation::tss_open
(void *ts_storage[ACE_TSS_KEYS_MAX])
{#if defined (ACE_PSOS)
u_long tss_base;
tss_base = (u_long) ts_storage;
t_setreg (0, PSOS_TASK_REG_TSS, tss_base);
void **tss_base_p = ts_storage;
for (u_int i = 0;
i < ACE_TSS_KEYS_MAX;
++i, ++tss_base_p)
*tss_base_p = 0;
return (void *) tss_base;
#elif defined (...)
// ...
� Examples
{ Unsupported but essential
portions of the API (e.g.,
thread-speci�c storage)
� Provided by POSIX, NT
� Not provided by
VxWorks, pSOS
� Emulation in user space is
necessary
{ Create a TSS emulation
class
{ Provide platform-speci�c
method implementations
6
ACE C++ Wrapper Tutorial
Network Programming Alternatives
USER
SPACE
KERNEL
SPACE
DOC MIDDLEWAREDOC MIDDLEWARE
SOCKETS AND SOCKETS AND TLITLITLI
OPENOPEN///CLOSECLOSE///PUTMSGPUTMSG///GETMSGGETMSG
STREAMSSTREAMSSTREAMSFRAMEWORKFRAMEWORK
LE
VE
L O
F
AB
ST
RA
CT
ION
TPITPINPINPIDLPIDLPI
HI
LO
� Communication
software can be
programmed at
several levels of
abstraction
� Di�erent levels
are appropriate
for di�erent tasks
7
ACE C++ Wrapper Tutorial
Navigating Through the Design Alternatives
Choosing the appropriate level of abstaction to program involves many
factors
� Performance
{ Higher levels may be less e�cient
� Functionality
{ Certain features, e.g., multicast, are not available at all levels
� Ease of programming
{ DOC middleware is typically easier to use
� Portability
{ The socket API is generally portable...
8
ACE C++ Wrapper TutorialOverview of DOC Middleware
INTERFACEINTERFACE
REPOSITORYREPOSITORY
IMPLEMENTATIONIMPLEMENTATION
REPOSITORYREPOSITORY
IDLIDLCOMPILERCOMPILER
DIIDII ORBORBINTERFACEINTERFACE
ORBORB CORECORE
operation()operation()
OBJECTOBJECT
ADAPTERADAPTER
in argsin args
out args + return valueout args + return value
CLIENTCLIENT
GIOPGIOP//IIOPIIOP
OBJECTOBJECT((SERVANTSERVANT))
IDLIDLSTUBSSTUBS
STANDARD INTERFACESTANDARD INTERFACE STANDARD LANGUAGE MAPPINGSTANDARD LANGUAGE MAPPING
ORB-ORB-SPECIFIC INTERFACESPECIFIC INTERFACE STANDARD PROTOCOLSTANDARD PROTOCOL
INTERFACEINTERFACE
REPOSITORYREPOSITORY
IMPLEMENTATIONIMPLEMENTATION
REPOSITORYREPOSITORY
IDLIDLCOMPILERCOMPILER
IDLIDLSKELETONSKELETON
DSIDSI
www.cs.wustl.edu/�schmidt/corba.html
� Helps simplify
many types of
applications
� Lets developers
work at higher
levels of
abstraction
� Examples include
CORBA, DCOM,
Java RMI, DCE,
Sun RPC
9
ACE C++ Wrapper Tutorial
Common DOC Middleware Features
� DOC middleware \stub/skeleton compiler" support
{ Automatically generate code to perform presentation layer conversions
� e.g., network byte-ordering and parameter marshaling
� DOC middleware runtime support
{ Handle network addressing and remote service identi�cation
{ Perform service registration, port monitoring, and service dispatching
{ Enforce authentication and security
{ Manage transport protocol selection and request delivery
{ Provide reliable operation delivery
{ Demultiplexing and dispatching
{ Concurrency and connection management
10
ACE C++ Wrapper TutorialDOC Middleware Limitations
� Some applications may need to access lower-level IPC mechanisms
directly to meet certain requirements
{ e.g., performance, functionality, portability, etc.
� Compared with direct use of sockets and TLI, DOC middleware may be
less e�cient due to
{ Presentation conversion processing and excessive data copying
{ Synchronous client-side and server-side stub behavior
{ Stop-and-wait ow control
{ Non-adaptive retransmission timer schemes
{ Non-optimized demultiplexing and concurrency models
11
ACE C++ Wrapper Tutorial
Standard APIs for Network IPC
USER
SPACE
DISTRIBUTED
APPLICATION 1
DISTRIBUTED
APPLICATION 3
DISTRIBUTED
APPLICATION 2
KERNEL
SPACE
SYSTEM V
TLI API
SYSTEM V
TLI APIBSD SOCKET
API
SOCKET
API
APPLICATION
PROCESS 3592
APPLICATION
PROCESS 4183
APPLICATION
PROCESS 8729
OSOS KERNEL KERNEL
PROTOCOL SERVICESPROTOCOL SERVICES
((TCPTCP//IPIP,, OSI,OSI, ETC ETC.).)
NETWORK
INTERFACE
� Sockets and TLI allow
access to lower-level
IPC mechanisms, e.g.:
{ TCP/IP
{ XNS and Novell
IPX NetWare
protocols
{ UNIX domain
sockets
{ OSI protocols
12
ACE C++ Wrapper Tutorial
Socket Taxonomy
LOCALLOCAL LOCALLOCAL//REMOTEREMOTE
ST
RE
AM
ST
RE
AM
ACTIVE
ACTIVE
PASSIVE
PASSIVE
DA
TA
DA
TA
GR
AM
GR
AM
CO
NN
EC
TE
DC
ON
NE
CT
ED
DA
TA
GR
AM
DA
TA
GR
AM
TY
PE
O
F
CO
MM
UN
ICA
TIO
N
SE
RV
ICE
TY
PE
O
F
CO
MM
UN
ICA
TIO
N
SE
RV
ICE
COMMUNICATION DOMAINCOMMUNICATION DOMAIN
CONNECTION
CONNECTION
ROLEROLE
accept(PF_UNIX)accept(PF_UNIX)listen() send()/recv()listen() send()/recv()
socket(PF_UNIX)socket(PF_UNIX)bind() sendto()bind() sendto()
socket(PF_UNX)socket(PF_UNX)bind() recvfrom()bind() recvfrom()
socket(PF_INET)socket(PF_INET)bind() recvfrom()bind() recvfrom()
socket(PF_INET)socket(PF_INET)bind() sendto()bind() sendto()
socket(PF_UNIX)socket(PF_UNIX)bind() connect() send()bind() connect() send()
socket(PF_UNIX)socket(PF_UNIX)bind() connect() recv()bind() connect() recv()
socket(PF_INET)socket(PF_INET) bind() connect() send() bind() connect() send()
socket(PF_INET)socket(PF_INET)bind() connect() recv()bind() connect() recv()
socket(PF_UNIX) bind()socket(PF_UNIX) bind()connect() send()/recv()connect() send()/recv()
accept(PF_INET)accept(PF_INET)listen() send()/recv()listen() send()/recv()
socket(PF_INET) bind()socket(PF_INET) bind()connect() send()/recv()connect() send()/recv()
� The Socket
API can be
classi�ed
along three
dimensions
13
ACE C++ Wrapper Tutorial
Problem with Sockets: Lack of Type-safety
int buggy_echo_server (u_short port_num)
{ // Error checking omitted.
sockaddr_in s_addr;
int s_fd = socket (PF_UNIX, SOCK_DGRAM, 0);
s_addr.sin_family = AF_INET;
s_addr.sin_port = port_num;
s_addr.sin_addr.s_addr = INADDR_ANY;
bind (s_fd, (sockaddr *) &s_addr,
sizeof s_addr);
int n_fd = accept (s_fd, 0, 0);
for (;;) {
char buf[BUFSIZ];
ssize_t n = read (s_fd, buf, sizeof buf);
if (n <= 0) break;
write (n_fd, buf, n);
}}
� I/O handles are
not amenable to
strong type
checking at
compile-time
� The adjacent
code contains
many subtle,
common bugs
14
ACE C++ Wrapper Tutorial
Problem with Sockets: Steep Learning Curve
Many socket/TLI API functions have complex semantics, e.g.:
� Multiple protocol families and address families
{ e.g., TCP, UNIX domain, OSI, XNS, etc.
� Infrequently used features, e.g.:
{ Broadcasting/multicasting
{ Passing open �le handles
{ Urgent data delivery and reception
{ Asynch I/O, non-blocking I/O, I/O-based and timer-based event
multiplexing
15
ACEC++
WrapperTutorial
Problem
withSockets:PoorlyStructured
socket()bind()connect()listen()accept()read()write()readv()writev()recv()send()recvfrom()sendto()recvmsg()sendmsg()setsockopt()getsockopt()getpeername()getsockname()gethostbyname()getservbyname()
�
NotethesocketAPIislinearratherthanhierarchical
{Thus,itgivesnohintsonhowtouseitcorrectly
�
Inaddition,thereisnoconsistencyamongnames...
16
ACEC++
WrapperTutorial
Problem
withSockets:Portability
�
Havingmultiple\standards,"i.e.,socketsandTLI,makesportability
di�cult,e.g.,
{Mayrequireconditionalcompilation
{Inaddition,relatedfunctionsarenotincludedinPOSIXstandards
�
e.g.,select,WaitForMultipleObjects,andpoll
�
PortabilitybetweenUNIXandWin32Socketsisproblematic,e.g.:
{Header�les
{Errornumbers
{Handlevs.descriptortypes
{Shutdownsemantics
{I/Ocontrolsandsocketoptions
17
ACEC++
WrapperTutorial
TheACEC++
IPCWrapperSolution
IPC
_S
AP A
SO
CK
_S
AP
TL
I_S
AP
FIF
O_S
AP
SP
IPE
_S
AP
SO
CK
ET
AP
I
TR
AN
SP
OR
T
LA
YE
R
INT
ER
FA
CE
AP
I
ST
RE
AM
PIP
E
AP
I
NA
ME
D P
IPE
AP
I
�
ACEprovidesC++\wrappers"thatencapsulateIPCprogramming
interfaceslikesocketsandTLI
{ThisisanexampleoftheWrapperFacadePattern
18
ACEC++
WrapperTutorial
IntentandStructureoftheWrapperFacadePattern
:Wrapper
:Wrapper
requ
est()1: req
uest ()
2: sp
ecific_req
uest()
:Wrappee
:Wrappee
specific_
request()
client
client
�
Intent
{Encapsulateslow-level,
stand-alonesystem
mechanismswithintype-safe,
modular,andportableclass
interfaces
�
ForcesResolved
{Avoidtedious,error-prone,
andnon-portablesystem
APIs
{Createcohesiveabstractions
19
ACEC++
WrapperTutorial
TheACEC++
SocketWrapperClassStructure
LO
CA
LL
OC
AL/R
EM
OT
E
STREAM
AC
TIV
E
PA
SSIV
E
DATAGRAM
CONNECTEDDATAGRAM
LO
CK
_C
on
necto
r L
SO
CK
_S
trea
m S
OC
K_
Co
nn
ecto
rS
OC
K_
Str
ea
m
SO
CK
_A
ccep
tor
SO
CK
_S
trea
m
SO
CK
_D
gra
m
LS
OC
K_
CO
Dg
ra
m S
OC
K_
CO
Dg
ra
m
LS
OC
K_
Dg
ra
m S
OC
K_
Dg
ra
m_
Bca
st
LS
OC
K_
Dg
ra
m S
OC
K_
Dg
ra
m
LS
OC
K_
Dg
ra
m
LS
OC
K_
Accep
tor
LS
OC
K_
Accep
tor
LS
OC
K_
Str
ea
mL
SO
CK
_S
trea
mSO
CK
_D
gra
m_
Mca
stS
OC
K_
Dg
ra
m_
Mca
st
SO
CK
_D
gra
m S
OC
K_
Dg
ra
m
TYPE OF COMMUNICATION SERVICE TYPE OF COMMUNICATION SERVICE
CO
MM
UN
ICA
TIO
N
DO
MA
INC
OM
MU
NIC
AT
ION
D
OM
AIN
CO
NN
EC
TIO
N
CO
NN
EC
TIO
N
RO
LE
RO
LE
�
Notehow
stand-alone
functionsare
replacedby
C++class
components
20
ACEC++
WrapperTutorial
SOCK
SAPFactoryClassInterfaces
classSOCK_Connector
{ public:
//Traits
typedefINET_AddrPEER_ADDR;
typedefSOCK_Stream
PEER_STREAM;
intconnect
(SOCK_Stream
&new_sap,
constINET_Addr
&raddr,
Time_Value*timeout,
constINET_Addr
&laddr);
//...
};
classSOCK_Acceptor
:publicSOCK
{ public:
//Traits
typedefINET_AddrPEER_ADDR;
typedefSOCK_StreamPEER_STREAM;
SOCK_Acceptor
(constINET_Addr&local_addr);
intaccept
(SOCK_Stream
&new_sap,
INET_Addr*,
Time_Value*);
//...
};
21
ACEC++
WrapperTutorial
SOCK
SAPStream
andAddressingClassInterfaces
classSOCK_Stream
:publicSOCK
{ public:
//Trait.
typedefINET_AddrPEER_ADDR;
ssize_tsend(constvoid*buf,
intn);
ssize_trecv(void*buf,
intn);
ssize_tsend_n(constvoid*buf,
intn);
ssize_trecv_n(void*buf,
intn);
intclose(void);
//...
};
classINET_Addr:publicAddr
{ public:
INET_Addr(u_shortport_number,
constcharhost[]);
u_shortget_port_number
(void);
int32get_ip_addr
(void);
//...
};
22
ACEC++
WrapperTutorial
OODesignInterlude
Q:WhydecoupletheSOCKAcceptorandtheSOCKConnectorfrom
SOCKStream?
A:ForthesamereasonsthatAcceptorandConnectoraredecoupled
fromSvcHandler,e.g.,
�
ASOCKStreamisonlyresponsiblefordatatransfer
{Regardlessofwhethertheconnectionisestablishedpassivelyor
actively
�
ThisensuresthattheSOCK*componentsarenotusedincorrectly...
{e.g.,youcan'taccidentallyreadorwriteonSOCKConnectorsor
SOCKAcceptors,etc.
23
ACE C++ Wrapper Tutorial
ACE C++ Wrapper echo server
int echo_server (u_short port_num)
{// Error handling omitted.
INET_Addr my_addr (port_num);
SOCK_Acceptor acceptor (my_addr);
SOCK_Stream new_stream;
acceptor.accept (new_stream);
for (;;)
{char buf[BUFSIZ];
// Error caught at compile time!
ssize_t n = acceptor.recv (buf, sizeof buf);
new_stream.send_n (buf, n);
}}
24
ACE C++ Wrapper Tutorial
A Generic Version of the Echo Server
template <class ACCEPTOR>
int echo_server (u_short port)
{// Local address of server (note use of traits).
ACCEPTOR::PEER_ADDR my_addr (port);
// Initialize the passive mode server.
ACCEPTOR acceptor (my_addr);
// Data transfer object (note use of traits).
ACCEPTOR::PEER_STREAM stream;
// Accept a new connection.
acceptor.accept (stream);
for (;;) {
char buf[BUFSIZ];
ssize_t n = stream.recv (buf, sizeof buf);
stream.send_n (buf, n);
}}
25
ACE C++ Wrapper Tutorial
Socket vs. ACE C++ Socket Wrapper Example
� The following slides illustrate di�erences between using the Socket
interface vs. the ACE C++ Socket wrappers
� The example is a simple client/server \network pipe" application that
behaves as follows:
1. Starts an iterative daemon at a well-known server port
2. Client connects to the server and transmits its standard input to the
server
3. The server prints this data to its standard output
� The server portion of the \network pipe" application may actually run
either locally or remotely...
26
ACE C++ Wrapper TutorialNetwork Pipe with Sockets
SERVERSERVERCLIENTCLIENT
socket()bind() (optional)
connect()
send()/recv()
socket()bind()listen()accept()
send()/recv()
2: ACTIVE
ROLE
3: SERVICE
PROCESSINGclose()
close()
NETWORK
1: PASSIVE
ROLE
27
ACE C++ Wrapper Tutorial
Network Pipe with ACE C++ Socket Wrappers
SERVERSERVERCLIENTCLIENT
SOCK_ConnectorSOCK_Stream
send()/recv()
SOCK_AcceptorSOCK_Stream
send()/recv()
2: ACTIVE
ROLE
3: SERVICE
PROCESSINGclose()
close()
NETWORK
1: PASSIVE
ROLE
28
ACE C++ Wrapper Tutorial
Running the Network Pipe Program
� e.g.,
% ./server &
% echo "hello world" | ./client localhost
client localhost.cs.wustl.edu%: hello world
� Note that the ACE C++ Socket wrapper example:
{ Requires much less code (about 1/2 to 2/3 less)
{ Provides greater clarity and less potential for errors
{ Operates at no loss of e�ciency
� Complete example available at URL:
{ www.cs.wustl.edu/�schmidt/IPC SAP-92.ps.gz
29
AC
EC
++
Wra
pp
erT
uto
rial Socket
Client
#define
PORT_NUM
10000
int
main
(int
argc,
char
*argv[])
{
struct
sockaddr_in
saddr;
struct
hostent
*hp;
char
*host
=argc
>1
?argv[1]
:"tango.cs.wustl.edu"
;
u_short
port_num
=argc
>2
htons
(argc
>2
?atoi
(argv[2])
:PORT_NUM);
char
buf[BUFSIZ];
int
s_fd;
int
w_bytes;
int
r_bytes;
int
n;
/*
Create
alocal
endpoint
of
communication
*/
s_fd
=socket
(PF_INET,
SOCK_STREAM,
0);
/*
Determine
IP
address
of
the
server
*/
hp
=gethostbyname
(host);
30
AC
EC
++
Wra
pp
erT
uto
rial
Socket
Client
(cont'
d)
/*
Set
up
the
address
information
to
contact
the
server
*/
memset
((void
*)
&saddr,
0,
sizeof
saddr);
saddr.sin_family
=AF_INET;
saddr.sin_port
=port_num;
memcpy
(&saddr.sin_addr,
hp->h_addr,
hp->h_length);
/*
Establish
connection
with
remote
server
*/
connect
(s_fd,
(struct
sockaddr
*)
&saddr,
sizeof
saddr);
/*
Send
data
to
server
(correctly
handles
"incomplete
writes"
due
to
flow
control)
*/
while
((r_bytes
=read
(0,
buf,
sizeof
buf))
>0)
for
(w_bytes
=0;
w_bytes
<r_bytes;
w_bytes
+=
n)
n=
write
(s_fd,
buf
+w_bytes,
r_bytes
-w_bytes);
/*
Explicitly
close
the
connection
*/
close
(s_fd);
return
0;
} 31
ACEC++WrapperTutorial
C++SocketWrapperClient
constu_shortPORT_NUM=10000;
intmain(intargc,char*argv[])
{
charbuf[BUFSIZ];
char*host=argc>1?argv[1]:"ics.uci.edu";
u_shortport_num=
htons(argc>2?atoi(argv[2]):PORT_NUM);
INET_Addrserver_addr(port_num,host);
SOCK_Streamcli_stream;
SOCK_Connectorconnector.
//Establishtheconnectionwithserver.
connector.connect(cli_stream,server_addr);
32
ACEC++WrapperTutorial
C++SocketWrapperClient(cont'd)
//Senddatatoserver(correctlyhandles
//"incompletewrites").
for(;;){
ssize_tr_bytes=read(0,buf,sizeofbuf);
cli_stream.send_n(buf,r_bytes);
}
//Explicitlyclosetheconnection.
cli_stream.close();
return0;
}
33
ACEC++WrapperTutorial
SocketServer
#definePORT_NUM10000
int
main(intargc,char*argv[])
{
u_shortport_num=
htons(argc>1?atoi(argv[1]):PORT_NUM);
structsockaddr_insaddr;
ints_fd,n_fd;
/*Createalocalendpointofcommunication*/
s_fd=socket(PF_INET,SOCK_STREAM,0);
/*Setuptheaddressinformationto
becomeaserver*/
memset((void*)&saddr,0,sizeofsaddr);
saddr.sin_family=AF_INET;
saddr.sin_port=port_num;
saddr.sin_addr.s_addr=INADDR_ANY;
/*Associateaddresswithendpoint*/
bind(s_fd,(structsockaddr*)&saddr,
sizeofsaddr);
/*Makeendpointlistenforservicerequests*/
listen(s_fd,5);
34
ACEC++WrapperTutorial
SocketServer(cont'd)
/*Performstheiterativeserveractivities*/
for(;;){
charbuf[BUFSIZ];
structsockaddr_incli_addr;
intr_bytes,cli_addr_len=sizeofcli_addr;
structhostent*hp;
/*Createanewendpointofcommunication*/
while((n_fd=accept(s_fd,(structsockaddr*)
&cli_addr,
&cli_addr_len))==-1
&&errno==EINTR)
continue;
if(n_fd==-1)
continue;
hp=gethostbyaddr((char*)&cli_addr.sin_addr,
cli_addr_len,AF_INET);
printf("client%s:",hp->h_name),fflush(stdout);
/*Readdatafromclient(terminateonerror)*/
while((r_bytes=read(n_fd,buf,sizeofbuf))>0)
write(1,buf,r_bytes);
/*Closethenewendpoint
(listeningendpointremainsopen)*/
close(n_fd);
}
}
35
ACEC++WrapperTutorial
C++WrapperSocketServer
constu_shortPORT_NUM=10000;
//SOCK_SAPServer.
int
main(intargc,char*argv[])
{
u_shortport_num=
argc==1?PORT_NUM:::atoi(argv[1]);
//Createaserver.
SOCK_Acceptoracceptor((INET_Addr)port_num);
SOCK_Streamnew_stream;
INET_Addrcli_addr;
36
ACEC++WrapperTutorial
C++WrapperSocketServer(cont'd)
//Performstheiterativeserveractivities.
for(;;){
charbuf[BUFSIZ];
//CreateanewSOCK_Streamendpoint(note
//automaticrestartiferrno==EINTR).
acceptor.accept(new_stream,&cli_addr);
printf("client%s:",cli_addr.get_host_name());
fflush(stdout);
//Readdatafromclient(terminateonerror).
for(;;){
ssize_tr_bytes;
r_bytes=new_stream.recv(buf,sizeofbuf);
if(r_bytes<=0)break;
write(1,buf,r_bytes);
}
//Closenewendpoint(listening
//endpointstaysopen).
new_stream.close();
}
37
ACEC++
WrapperTutorial
ACEC++
WrapperDesignPrinciples
�
Enforcetypesafetyatcompile-time
�
Allowcontrolledviolationsoftypesafety
�
Simplifyforthecommoncase
�
Replaceone-dimensionalinterfaceswithhierarchicalclasscategories
�
Enhanceportabilitywithparameterizedtypes
�
Inlineperformancecriticalmethods
�
De�neauxiliaryclassestohideerror-pronedetails
38
ACEC++
WrapperTutorial
EnforceTypesafetyatCompile-Time
Socketscannotdetectcertainerrorsatcompile-time,e.g.,
ints_sd=socket(PF_INET,SOCK_STREAM,
0);
//...
bind(s_sd,...);//Bindaddress.
listen(s_sd);//Makeapassive-mode
socket.
//Errornotdetecteduntilrun-time.
read(s_sd,buf,sizeofbuf);
ACEenforcestype-safetyatcompile-timeviafactories,e.g.:
SOCK_Acceptor
acceptor(port);
//Error:recv()notamethodofSOCK_Acceptor.
acceptor.recv
(buf,sizeofbuf);
39
ACEC++
WrapperTutorial
AllowControlledViolationsofTypesafety
MakeiteasytousetheC++Socketwrapperscorrectly,hardtouseit
incorrectly,butnotimpossibletouseitinwaystheclassdesignersdidnot
anticipate
�
e.g.,itmaybenecessarytoretrievetheunderlyingsockethandle:
fd_setrd_sds;
FD_ZERO(&rd_sds);
FD_SET(acceptor.get_handle
(),&rd_sds);
select(acceptor.get_handle
()+1,&rd_sds,0,0,0);
40
ACEC++
WrapperTutorial SupplyDefaultParameters
SOCK_Connector
(SOCK_Stream
&new_stream,
constAddr&remote_sap,
ACE_Time_Value
*timeout=0,
constAddr&local_sap=Addr::sap_any,
intprotocol_family
=PF_INET,
intprotocol=0);
Theresultisextremelyconciseforthecommoncase:
SOCK_Stream
stream;
//Compilersuppliesdefaultvalues.
SOCK_Connector
con(stream,INET_Addr(port,host));
41
ACEC++
WrapperTutorial
De�neParsimoniousInterfaces
e.g.,useLSOCKtopasssockethandles:
LSOCK_Stream
stream;
LSOCK_Acceptor
acceptor("/tmp/foo");
acceptor.accept
(stream);
stream.send_handle
(stream.get_handle
());
versus
LSOCK::send_handle(constHANDLEsd)const{
u_chara[2];ioveciov;msghdrsend_msg;
a[0]=0xab,a[1]=0xcd;
iov.iov_base=(char*)a;iov.iov_len=sizeofa;
send_msg.msg_iov=&iov;send_msg.msg_iovlen=1;
send_msg.msg_name=(char*)0;
send_msg.msg_namelen=0;
send_msg.msg_accrights=(char*)&sd;
send_msg.msg_accrightslen=sizeofsd;
returnsendmsg(this->get_handle(),&send_msg,0);
42
ACEC++
WrapperTutorial
CombineMultipleOperationsintoOneOperation
Creatingaconventionalpassive-modesocketrequiresmultiplecalls:
ints_sd=socket(PF_INET,SOCK_STREAM,
0);
sockaddr_in
addr;
memset(&addr,0,sizeofaddr);
addr.sin_family
=AF_INET;
addr.sin_port
=htons(port);
addr.sin_addr.s_addr
=INADDR_ANY;
bind(s_sd,&addr,addr_len);
listen(s_sd);
//...
SOCKAcceptorcombinesthisintoasingleoperation:
SOCK_Acceptor
acceptor((INET_Addr)
port);
43
ACE C++ Wrapper Tutorial
Create Hierarchical Class Categories
LSOCK LSOCKDgramDgram
SOCK SOCKDgramDgram
SOCK SOCKCODgramCODgram
LSOCK LSOCKCODgramCODgram
LSOCK LSOCKConnectorConnector
LSOCK LSOCKAcceptorAcceptor
SOCK SOCKAcceptorAcceptor
SOCK SOCKConnectorConnector
SOCK SOCK
AA
LSOCK LSOCK
AA
IPCIPCSAPSAP
AA
SOCK SOCKDgramDgramMcastMcast
SOCK SOCKDgramDgramBcastBcast
GROUPGROUP
COMMCOMM
DATAGRAMDATAGRAM
COMMCOMM
STREAMSTREAM
COMMCOMM
CONNECTIONCONNECTION
ESTABLISHMENTESTABLISHMENT
SOCKSOCKStreamStream
LSOCKLSOCKStreamStream
� Shared behavior is isolated in base classes
� Derived classes implement di�erent communication services,
communication domains, and connection roles
44
ACE C++ Wrapper Tutorial
Enhance Portability with Parameterized Types
OSOS KERNEL KERNEL
PROTOCOL MECHANISMSPROTOCOL MECHANISMS
((TCPTCP//IPIP,, OSI,OSI, ETC ETC.).)
USERUSER
SPACESPACE
DISTRIBUTED
APPLICATION 1
APPLICATIONAPPLICATION11 DISTRIBUTED
APPLICATION 3
APPLICATIONAPPLICATION33DISTRIBUTED
APPLICATION 2
APPLICATIONAPPLICATION22
KERNELKERNEL
SPACESPACE
BSD SOCKET
API
COMMON INTERFACECOMMON INTERFACE
((PARAMETERIZED TYPESPARAMETERIZED TYPES))
SOCKETSOCKET
API
SOCK_SAP
BSD SOCKET
API
SYSTEM VTLI API
TLI_SAP
NETWORK
INTERFACE
45
ACE C++ Wrapper Tutorial
Enhance Portability with Parameterized Types (cont'd)
Switching wholesale between sockets and TLI simply requires instantiating
a di�erent C++ wrapper, e.g.,
// Conditionally select IPC mechanism.
#if defined (USE_SOCKETS)
typedef SOCK_Acceptor PEER_ACCEPTOR;
#elif defined (USE_TLI)
typedef TLI_Acceptor PEER_ACCEPTOR;
#endif // USE_SOCKETS.
int main (void)
{// ...
// Invoke the echo_server with appropriate
// network programming interfaces.
echo_server<PEER_ACCEPTOR> (port);
}46
ACE C++ Wrapper Tutorial
Inline Performance Critical Methods
Inlining is time and space e�cient since key methods are very short:
class SOCK_Stream : public SOCK
{public:
ssize_t send (const void *buf, size_t n)
{return ACE_OS::send (this->get_handle (), buf, n);
}ssize_t recv (void *buf, size_t n)
{return ACE_OS::recv (this->get_handle (), buf, n);
}};
47
ACEC++
WrapperTutorial
De�neAuxiliaryClassestoHideError-ProneDetails
StandardCsocketaddressingisawkwardanderror-prone
�
e.g.,easytoneglecttozero-outasockaddrinorconvertport
numberstonetworkbyte-order,etc.
ACEC++SocketWrappersde�neclassestohandlethesedetails
classINET_Addr:publicAddr{
public:
INET_Addr(u_shortport,longip_addr=0){
memset(&this->inet_addr_,
0,sizeofthis->inet_addr_);
this->inet_addr_.sin_family
=AF_INET;
this->inet_addr_.sin_port
=htons(port);
memcpy(&this->inet_addr_.sin_addr,
&ip_addr,sizeofip_addr);
} //...
private:
sockaddr_ininet_addr_;
};
48
ACEC++
WrapperTutorial
SummaryofACEC++
SocketWrapperDesign
Principles
�
Domainanalysisidenti�esandgroupsrelatedclassesofexistingAPI
behavior
{Examplesubdomainsinclude
�
Localcontextmanagementandoptions,datatransfer,
connection/terminationhandling,etc.
�
Datagramsvs.streams
�
Localvs.remoteaddressing
�
Activevs.passiveconnectionroles
�
Theserelationshipsaredirectlyre ectedintheACEC++Socket
wrapperinheritancehierarchy
49
ACEC++
WrapperTutorial
SummaryofACEC++
SocketWrapperDesign
Principles(cont'd)
�
TheACEC++Socketwrappersaredesignedtomaximizereusability
andsharingofcomponents
{Inheritanceisusedtofactoroutcommonalityanddecouplevariation
e.g.,
�
Pushcommonservices\upwards"intheinheritancehierarchy
�
Factoroutvariationsinclient/serverportionsofsocketAPI
�
Decoupledatagramvs.streamoperations,localvs.remote,etc.
{Inheritancealsosupports\functionalsubsetting"
�
e.g.,passingopen�lehandles...
50
ACEC++
WrapperTutorial
SummaryofACEC++
SocketWrapperDesign
Principles(cont'd)
�
Performanceimprovementstechniquesinclude:
{Inlinefunctionsareusedtoavoidadditionalfunctioncallpenalties
{Dynamicbindingisusedsparinglytoreducetime/spaceoverhead
�
i.e.,itiseliminatedforrecv/sendpath
�
Notethedi�erencebetweenthecompositionvs.
decomposition/compositionaspectsindesigncomplexity
{i.e.,ACEC++Socketwrappersareprimarilyanexercisein
compositionsincethebasiccomponentsalreadyexist
{MorecomplexOOdesignsinvolvebothaspects...
�
e.g.,theACEStreams,ServiceCon�gurator,andReactor
frameworks,etc.
51
ACEC++
WrapperTutorial
ConcludingRemarks
�
De�ningC++wrappersfornativeOSAPIssimpli�esthedevelopment
ofcorrect,portable,andextensibleapplications
{C++inlinefunctionsensurethatperformanceisn'tsacri�ced
�
ACEcontainsmanyC++wrappersthatencapsulateUNIX,Win32,and
RTOSAPIsinterfaces
{e.g.,sockets,TLI,namedpipes,STREAMpipes,etc.
�
ACEcanbeintegratedconvenientlywithCORBAandDCOMprovidea
exiblehigh-performance,real-timedevelopmentframework
52