3 This program illustrates how to implement a simple client and server
4 using CORBA, IIOP, and asynchronous method invocations (AMI). Client
5 applications can use this service to download and display files from a
6 CORBA server on the network. The core functionality of this program
9 * Client applications register callbacks with servers using
10 the Observer pattern. The server will ``push'' chunks of
11 data to the client. Thus, the client will play the role of
12 a ``server,'' as well.
14 * Operations in the IDL interface will use exceptions to propagate
15 problems back to clients.
17 * The CORBA Naming Service is used to bind and resolve object
18 references, rather than using a file.
21 Basic design of the programs:
23 The basic idea used in both the client and and the server is to use
24 AMI when performing all requests. This allows both the client and the
25 server to perform other tasks without having to wait for a given task
28 The client first activates its Callback object, and then
29 asynchronously registers a reference to its Callback object with the
30 server's Push_Iterator_Factory. The Push_Iterator_Factory then
31 creates an AMI reply handler "Callback_Handler" for the requested file
32 that asynchronously sends chunks of data to the client's Callback
33 object. After creating and running the Callback_Handler, the
34 Push_Iterator_Factory returns the Metadata containing the content type
35 and modification date of the file to client. Since the Callback was
36 registered using the Push_Iterator_Factory using AMI, an AMI reply
37 handler called "Push_Iterator_Handler" on the client side will receive
38 and handle the Metadata returned from the Push_Iterator_Factory. The
39 Push_Iterator_Handler then passes the received Metadata to the
40 Callback object. The Callback will spawn an external viewer once both
41 the Metadata and the entire file content have been received. The
42 Callback object is designed to correctly handle the case where the
43 content is received before the Metadata, and vice versa. This
44 operation is thread-safe. Note that no threads are created at the
45 application level in neither the client nor the server, yet
46 concurrency is still achieved due to the fact that AMI is used on both
49 A schematic of the operations involved follows:
53 Push_Iterator_Handler - activate
54 Callback - activate Push_Iterator_Factory - activate
56 sendc_register_callback() ---> register_callback()
57 Callback_Handler - activate
59 next_chunk() <--- sendc_next_chunk()
63 next_chunk() <--- sendc_next_chunk()
65 register_callback() <--- Metadata - returned
66 Metadata passed to Callback
68 next_chunk() <--- sendc_next_chunk()
72 next_chunk() <--- sendc_next_chunk()
74 Note that the Callback_Handler will not send the next chunk until it
75 receives a reply from the client's Callback object. This ensures that
76 the client receives all chunks of data in the proper order.
79 The client program performs the following activities:
81 1. From the command-line, it reads the name of the pathname
82 you want to download. It then initializes the client-side
83 ORB and uses resolve_initial_references() to obtain a
84 reference to a Naming Service (which must be running). This
85 object reference is then downcast via _narrow() to an
86 object reference for a CosNaming::NamingContext interface,
87 which is then used to resolve the object reference that the
88 server bound earlier. After narrowing this to the Server
89 interface, the sendc_register_callback() operation is
90 called via the object reference to pass asynchronously pass
91 the Callback interface from the client to the server, which
92 then uses AMI to push chunks of the file to the client.
94 2. The server calls the sendc_next_chunk() method on the
95 callback, passing in the offset and the next chunk.
97 3. When the client receives the next_chunk() callback that
98 contains a chunk of the file, the contents are written into
99 a temporary file created in your a cache (e.g.,
100 /tmp/yourloginname) on the local host. Then, an external
101 viewer is spawned to display the file. The type of viewer
102 to spawn is determined by examining the the content_type_
103 metadata returned by the server.
106 The example can be run as follows:
108 1. Start the Name Service:
110 $ NameService -o /tmp/ns.ior
112 2. Start the SMI Content Server:
114 $ server -ORBInitRef NameService=file:///tmp/ns.ior
116 3. Request a file using the client:
118 $ client -ORBInitRef NameService=file:///tmp/ns.ior \
119 ~/foo.jpg ~/bar.pdf ~/baz.jpg
121 This example can service multiple file requests.
124 Server output should look like the following:
126 $ ./server -ORBInitRef NameService=file:///tmp/ns.ior
127 Bound <Push_Iterator_Factory> to <IOR:010000002300000039434c3a5765625f5365727665722f4974657261746f725f466163746f72793a312e300001000000000000007c000000010102001400000076616c696e6f722e6563652e7563692e65647500489700001b00000014010f00525354a6ae4e392ad209000000000001000000010000000003000000000000000800000001000000004f4154010000001400000001ac854001000100000000000901010000000000004f41540400000001ac0000> in Name Service.
129 Received request for file: </home/myhome/foo.jpg>
130 Sending chunk 1 from /home/myhome/foo.jpg of size <8192>
131 Received request for file: </home/myhome/bar.pdf>
132 Sending chunk 1 from /home/myhome/bar.pdf of size <8192>
133 Received request for file: </home/myhome/baz.jpg>
134 Sending chunk 1 from /home/myhome/baz.jpg of size <8192>
135 Sending chunk 2 from /home/myhome/baz.jpg of size <8192>
136 Sending chunk 2 from /home/myhome/foo.jpg of size <8192>
137 Sending chunk 2 from /home/myhome/bar.pdf of size <8192>
138 Sending chunk 3 from /home/myhome/foo.jpg of size <8192>
139 Sending chunk 3 from /home/myhome/baz.jpg of size <8192>
140 Sending chunk 3 from /home/myhome/bar.pdf of size <8192>
141 Sending chunk 4 from /home/myhome/baz.jpg of size <8192>
142 Sending chunk 4 from /home/myhome/foo.jpg of size <8192>
143 Sending chunk 4 from /home/myhome/bar.pdf of size <8192>
144 Sending chunk 5 from /home/myhome/baz.jpg of size <6997>
145 Sending chunk 5 from /home/myhome/foo.jpg of size <4573>
146 Sending chunk 5 from /home/myhome/bar.pdf of size <8192>
147 Sending chunk 6 from /home/myhome/bar.pdf of size <8192>
148 Sending chunk 7 from /home/myhome/bar.pdf of size <8192>
149 Sending chunk 8 from /home/myhome/bar.pdf of size <8192>
151 Sending chunk 138 from /home/myhome/bar.pdf of size <8192>
152 Sending chunk 139 from /home/myhome/bar.pdf of size <5832>
155 Notice that requests for chunks of data from three separate files occur
159 Client output should look similar to:
161 $ ./client -ORBInitRef NameService=file:///tmp/ns.ior ~/foo.jpg ~/bar.pdf \
163 Retrieved file has the following characteristics:
164 Modification Date: Wed, 01 Mar 2000 04:28:18 GMT
165 Content Type: image/jpeg
166 Retrieved file has the following characteristics:
167 Modification Date: Fri, 24 Mar 2000 06:25:23 GMT
168 Content Type: image/jpeg
169 Retrieved file has the following characteristics:
170 Modification Date: Sat, 19 Feb 2000 03:19:50 GMT
171 Content Type: application/pdf
172 Wrote retrieved data to file </tmp/ace-file-0oklyh>
173 Spawned viewer <xv> with PID <11631>.
174 Wrote retrieved data to file </tmp/ace-file-qyLaLc>
175 Spawned viewer <xv> with PID <11632>.
176 Wrote retrieved data to file </tmp/ace-file-2VHw4l>
177 Spawned viewer <acroread> with PID <11633>.