In this more advanced example, we will see how we can set up a client exchanging byte sequences with server. The idl definition (byteseq.idl) covers in-, out- and inout-parameters and looks like:
Example 5-22. byteseq.idl
module Examples {
module ByteSeq {
typedef sequence<octet> Chunk;
interface Storage {
void set (in Chunk chunk);
Chunk get ();
};
};
};| File | Usage for Client | Usage for Server |
|---|---|---|
| byteseq.h | readonly | readonly |
| byteseq-common.c | readonly | readonly |
| byteseq-stubs.c | readonly | - |
| byteseq-skels.c | - | readonly |
| byteseq-skelimpl.c | - | template for user code |
Example 5-23. byteseq-client.c
/* byteseq-client.c hacked by Frank Rehberger
* <F.Rehberger@xtradyne.de>. */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <orbit/orbit.h>
#include "byteseq.h"
#include "examples-toolkit.h" /* ie. etk_etk_abort_if_exception() */
static CORBA_ORB global_orb = CORBA_OBJECT_NIL; /* global orb */
/* Is called in case of process signals. it invokes CORBA_ORB_shutdown()
* function, which will terminate the processes main loop.
*/
static
void
client_shutdown (int sig)
{
CORBA_Environment local_ev[1];
CORBA_exception_init(local_ev);
if (global_orb != CORBA_OBJECT_NIL)
{
CORBA_ORB_shutdown (global_orb, FALSE, local_ev);
etk_abort_if_exception (local_ev, "caught exception");
}
}
/* Inits ORB @orb using @argv arguments for configuration. For each
* ORBit options consumed from vector @argv the counter of @argc_ptr
* will be decremented. Signal handler is set to call
* echo_client_shutdown function in case of SIGINT and SIGTERM
* signals. If error occures @ev points to exception object on
* return.
*/
static
void
client_init (int *argc_ptr,
char *argv[],
CORBA_ORB *orb,
CORBA_Environment *ev)
{
/* init signal handling */
signal(SIGINT, client_shutdown);
signal(SIGTERM, client_shutdown);
/* create Object Request Broker (ORB) */
(*orb) = CORBA_ORB_init(argc_ptr, argv, "orbit-local-mt-orb", ev);
if (etk_raised_exception(ev)) return;
}
/* Releases @servant object and finally destroys @orb. If error
* occures @ev points to exception object on return.
*/
static
void
client_cleanup (CORBA_ORB orb,
Examples_ByteSeq_Storage servant,
CORBA_Environment *ev)
{
/* releasing managed object */
CORBA_Object_release(servant, ev);
if (etk_raised_exception(ev)) return;
/* tear down the ORB */
if (orb != CORBA_OBJECT_NIL)
{
/* going to destroy orb.. */
CORBA_ORB_destroy(orb, ev);
if (etk_raised_exception(ev)) return;
}
}
/**
*
*/
static
void
client_run_set (Examples_ByteSeq_Storage servant,
CORBA_Environment *ev)
{
CORBA_long LEN = 4*1024; /* 4KB */
CORBA_long ITER = 10;
CORBA_long iter = 0;
Examples_ByteSeq_Chunk* chunk = NULL;
/* flood service witth large chunks of byte streams */
for (iter = 0; iter < ITER; ++iter)
{
CORBA_long len = 0;
CORBA_octet elem = 'A';
g_print ("+");
chunk = ORBit_sequence_alloc (TC_CORBA_sequence_CORBA_octet,0);
for (len = 0; len < LEN; ++len)
ORBit_sequence_append (chunk, &elem);
Examples_ByteSeq_Storage_set (servant, chunk, ev);
if (etk_raised_exception(ev)) return;
CORBA_free (chunk);
}
}
/**
*
*/
static
void
client_run_get (Examples_ByteSeq_Storage servant,
CORBA_Environment *ev)
{
CORBA_long n=10;
CORBA_long i=0;
Examples_ByteSeq_Chunk* chunk = NULL;
/* increment sequence length, beginning with 0 up to 2048 */
for (i=0; i<n; ++i)
{
g_print ("-");
chunk = Examples_ByteSeq_Storage_get (servant, ev);
if (etk_raised_exception(ev)) return;
CORBA_free (chunk);
}
}
/*
* main
*/
int
main(int argc, char* argv[])
{
CORBA_char *filename = "byteseq.ref";
Examples_ByteSeq_Storage servant = CORBA_OBJECT_NIL;
CORBA_Environment ev[1];
CORBA_exception_init(ev);
client_init (&argc, argv, &global_orb, ev);
etk_abort_if_exception(ev, "init failed");
g_print ("Reading service reference from file \"%s\"\n", filename);
servant = (Examples_ByteSeq_Storage)
etk_import_object_from_file (global_orb,
filename,
ev);
etk_abort_if_exception(ev, "exporting IOR failed");
client_run_set (servant, ev);
etk_abort_if_exception(ev, "client stopped");
client_run_get (servant, ev);
etk_abort_if_exception(ev, "client stopped");
client_cleanup (global_orb, servant, ev);
etk_abort_if_exception(ev, "cleanup failed");
exit (0);
}
Example 5-24. byteseq-server.c
/*
* byteseq-server program. Hacked from Examples test suite
* by Frank Rehberger <F.Rehberger@xtradyne.de>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <orbit/orbit.h>
#include "byteseq.h"
#include "byteseq-skelimpl.c"
#include "examples-toolkit.h" /* provides etk_abort_if_exception() */
static CORBA_ORB global_orb = CORBA_OBJECT_NIL; /* global orb */
static PortableServer_POA root_poa = CORBA_OBJECT_NIL; /* root POA
/* Is called in case of process signals. it invokes CORBA_ORB_shutdown()
* function, which will terminate the processes main loop.
*/
static
void
server_shutdown (int sig)
{
CORBA_Environment local_ev[1];
CORBA_exception_init(local_ev);
if (global_orb != CORBA_OBJECT_NIL)
{
CORBA_ORB_shutdown (global_orb, FALSE, local_ev);
etk_abort_if_exception (local_ev, "caught exception");
}
}
/* Inits ORB @orb using @argv arguments for configuration. For each
* ORBit options consumed from vector @argv the counter of @argc_ptr
* will be decremented. Signal handler is set to call
* echo_server_shutdown function in case of SIGINT and SIGTERM
* signals. If error occures @ev points to exception object on
* return.
*/static
void
server_init (int *argc_ptr,
char *argv[],
CORBA_ORB *orb,
PortableServer_POA *poa,
CORBA_Environment *ev)
{
PortableServer_POAManager poa_manager = CORBA_OBJECT_NIL;
CORBA_Environment local_ev[1];
CORBA_exception_init(local_ev);
/* init signal handling */
signal(SIGINT, server_shutdown);
signal(SIGTERM, server_shutdown);
/* create Object Request Broker (ORB) */
(*orb) = CORBA_ORB_init(argc_ptr, argv, "orbit-local-mt-orb", ev);
if (etk_raised_exception(ev))
goto failed_orb;
(*poa) = (PortableServer_POA)
CORBA_ORB_resolve_initial_references(*orb, "RootPOA", ev);
if (etk_raised_exception(ev))
goto failed_poa;
poa_manager = PortableServer_POA__get_the_POAManager(*poa, ev);
if (etk_raised_exception(ev))
goto failed_poamanager;
PortableServer_POAManager_activate(poa_manager, ev);
if (etk_raised_exception(ev))
goto failed_activation;
CORBA_Object_release ((CORBA_Object) poa_manager, ev);
return;
failed_activation:
failed_poamanager:
CORBA_Object_release ((CORBA_Object) poa_manager, local_ev);
failed_poa:
CORBA_ORB_destroy(*orb, local_ev);
failed_orb:
return;
}
/* Entering main loop @orb handles incoming request and delegates to
* servants. If error occures @ev points to exception object on
* return.
*/
static void
server_run (CORBA_ORB orb,
CORBA_Environment *ev)
{
/* enter main loop until SIGINT or SIGTERM */
CORBA_ORB_run(orb, ev);
if (etk_raised_exception(ev)) return;
/* user pressed SIGINT or SIGTERM and in signal handler
* CORBA_ORB_shutdown(.) has been called */
}
/* Releases @servant object and finally destroys @orb. If error
* occures @ev points to exception object on return.
*/
static void
server_cleanup (CORBA_ORB orb,
PortableServer_POA poa,
CORBA_Object ref,
CORBA_Environment *ev)
{
PortableServer_ObjectId *objid = NULL;
objid = PortableServer_POA_reference_to_id (poa, ref, ev);
if (etk_raised_exception(ev)) return;
/* Servant: deactivatoin - will invoke __fini destructor */
PortableServer_POA_deactivate_object (poa, objid, ev);
if (etk_raised_exception(ev)) return;
PortableServer_POA_destroy (poa, TRUE, FALSE, ev);
if (etk_raised_exception(ev)) return;
CORBA_free (objid);
CORBA_Object_release ((CORBA_Object) poa, ev);
if (etk_raised_exception(ev)) return;
CORBA_Object_release (ref, ev);
if (etk_raised_exception(ev)) return;
/* ORB: tear down the ORB */
if (orb != CORBA_OBJECT_NIL)
{
/* going to destroy orb.. */
CORBA_ORB_destroy(orb, ev);
if (etk_raised_exception(ev)) return;
}
}
/* Creates servant and registers in context of ORB @orb. The ORB will
* delegate incoming requests to specific servant object. @return
* object reference. If error occures @ev points to exception object
* on return.
*/
static CORBA_Object
server_activate_service (CORBA_ORB orb,
PortableServer_POA poa,
CORBA_Environment *ev)
{
Examples_ByteSeq_Storage ref = CORBA_OBJECT_NIL;
ref = impl_Examples_ByteSeq_Storage__create (poa, ev);
if (etk_raised_exception(ev))
return CORBA_OBJECT_NIL;
return ref;
}
/*
* main
*/
int
main (int argc, char *argv[])
{
CORBA_Object servant = CORBA_OBJECT_NIL;
CORBA_char filename[] = "byteseq.ref";
CORBA_Environment ev[1];
CORBA_exception_init(ev);
server_init (&argc, argv, &global_orb, &root_poa, ev);
etk_abort_if_exception(ev, "failed ORB init");
servant = server_activate_service (global_orb, root_poa, ev);
etk_abort_if_exception(ev, "failed activating service");
g_print ("Writing service reference to: %s\n\n", filename);
etk_export_object_to_file (global_orb,
servant,
filename,
ev);
etk_abort_if_exception(ev, "failed exporting IOR");
server_run (global_orb, ev);
etk_abort_if_exception(ev, "failed entering main loop");
server_cleanup (global_orb, root_poa, servant, ev);
etk_abort_if_exception(ev, "failed cleanup");
exit (0);
}Example 5-25. byteseq-skelimpl.c
/* This is a template file generated by command */
/* orbit-idl-2 --skeleton-impl byteseq.idl */
/* User must edit this file, inserting servant */
/* specific code between markers. */
#include "byteseq.h"
/*** App-specific servant structures ***/
typedef struct
{
POA_Examples_ByteSeq_Storage servant;
PortableServer_POA poa;
/* ------ add private attributes here ------ */
Examples_ByteSeq_Chunk * chunk;
/* ------ ---------- end ------------ ------ */
} impl_POA_Examples_ByteSeq_Storage;
/*** Implementation stub prototypes ***/
static void
impl_Examples_ByteSeq_Storage__fini(impl_POA_Examples_ByteSeq_Storage *
servant, CORBA_Environment * ev);
static void
impl_Examples_ByteSeq_Storage_set(impl_POA_Examples_ByteSeq_Storage * servant,
const Examples_ByteSeq_Chunk * chunk,
CORBA_Environment * ev);
static Examples_ByteSeq_Chunk
*impl_Examples_ByteSeq_Storage_get(impl_POA_Examples_ByteSeq_Storage *
servant, CORBA_Environment * ev);
/*** epv structures ***/
static PortableServer_ServantBase__epv impl_Examples_ByteSeq_Storage_base_epv
= {
NULL, /* _private data */
(gpointer) & impl_Examples_ByteSeq_Storage__fini, /* finalize routine */
NULL, /* default_POA routine */
};
static POA_Examples_ByteSeq_Storage__epv impl_Examples_ByteSeq_Storage_epv = {
NULL, /* _private */
(gpointer) & impl_Examples_ByteSeq_Storage_set,
(gpointer) & impl_Examples_ByteSeq_Storage_get
};
/*** vepv structures ***/
static POA_Examples_ByteSeq_Storage__vepv impl_Examples_ByteSeq_Storage_vepv = {
&impl_Examples_ByteSeq_Storage_base_epv,
&impl_Examples_ByteSeq_Storage_epv,
};
/*** Stub implementations ***/
static Examples_ByteSeq_Storage
impl_Examples_ByteSeq_Storage__create(PortableServer_POA poa,
CORBA_Environment * ev)
{
Examples_ByteSeq_Storage retval;
impl_POA_Examples_ByteSeq_Storage *newservant;
PortableServer_ObjectId *objid;
newservant = g_new0(impl_POA_Examples_ByteSeq_Storage, 1);
newservant->servant.vepv = &impl_Examples_ByteSeq_Storage_vepv;
newservant->poa =
(PortableServer_POA) CORBA_Object_duplicate((CORBA_Object) poa, ev);
POA_Examples_ByteSeq_Storage__init((PortableServer_Servant) newservant,
ev);
/* Before servant is going to be activated all
* private attributes must be initialized. */
/* ------ init private attributes here ------ */
newservant->chunk = ORBit_sequence_alloc (TC_CORBA_sequence_CORBA_octet, 64);
/* ------ ---------- end ------------- ------ */
objid = PortableServer_POA_activate_object(poa, newservant, ev);
CORBA_free(objid);
retval = PortableServer_POA_servant_to_reference(poa, newservant, ev);
return retval;
}
/**
* impl_Examples_ByteSeq_Storage__fini
*
* Destructor called after servant has been deactivated finally.
* In case any operation is invoked, application is being delayed.
**/
static void
impl_Examples_ByteSeq_Storage__fini(impl_POA_Examples_ByteSeq_Storage *
servant, CORBA_Environment * ev)
{
CORBA_Object_release((CORBA_Object) servant->poa, ev);
/* No further remote method calls are delegated to
* servant and you may free your private attributes. */
/* ------ free private attributes here ------ */
CORBA_free (servant->chunk);
/* ------ ---------- end ------------- ------ */
POA_Examples_ByteSeq_Storage__fini((PortableServer_Servant) servant, ev);
g_free(servant);
}
static void
impl_Examples_ByteSeq_Storage_set(impl_POA_Examples_ByteSeq_Storage * servant,
const Examples_ByteSeq_Chunk * chunk,
CORBA_Environment * ev)
{
/* ------ insert method code here ------ */
ORBit_sequence_set_size (servant->chunk, chunk->_length);
{
CORBA_long i=0;
for (i = 0; i < chunk->_length; ++i)
ORBit_sequence_index (servant->chunk, i)
= ORBit_sequence_index (chunk, i);
}
/* ------ ---------- end ------------ ------ */
}
static Examples_ByteSeq_Chunk *
impl_Examples_ByteSeq_Storage_get(impl_POA_Examples_ByteSeq_Storage * servant,
CORBA_Environment * ev)
{
Examples_ByteSeq_Chunk *retval;
/* ------ insert method code here ------ */
retval = ORBit_sequence_alloc (TC_CORBA_sequence_CORBA_octet,
servant->chunk->_length);
{
CORBA_long i=0;
for (i = 0; i < servant->chunk->_length; ++i)
ORBit_sequence_index (retval, i)
= ORBit_sequence_index (servant->chunk, i);
}
/* ------ ---------- end ------------ ------ */
return retval;
}
Example 5-26. Makefile
PREFIX ?= /usr
CC = gcc
TARGETS=byteseq-client byteseq-server
ORBIT_IDL=$(PREFIX)/bin/orbit-idl-2
CFLAGS=-g -DORBIT2=1 -D_REENTRANT -I$(PREFIX)/include/orbit-2.0 \
-I$(PREFIX)/include/linc-1.0 -I$(PREFIX)/include/glib-2.0 \
-I$(PREFIX)/lib/glib-2.0/include
LDFLAGS= -Wl,--export-dynamic -L$(PREFIX)/lib -lORBit-2 -llinc -lgmodule-2.0 \
-ldl -lgobject-2.0 -lgthread-2.0 -lpthread -lglib-2.0 -lm \
-lORBitCosNaming-2
IDLOUT=byteseq-common.c byteseq-stubs.c byteseq-skels.c byteseq.h
all: $(IDLOUT) byteseq-client byteseq-server
byteseq-server.o: byteseq-server.c byteseq-skelimpl.c
byteseq-client : byteseq-client.o byteseq-stubs.o byteseq-common.o examples-toolkit.o
byteseq-server : byteseq-server.o byteseq-skels.o byteseq-common.o examples-toolkit.o
$(IDLOUT): byteseq.idl
$(ORBIT_IDL) byteseq.idl
%-skelimpl.c: %.idl
$(ORBIT_IDL) --skeleton-impl $^
clean:
rm -rf *.o *~ $(IDLOUT)
distclean: clean
rm -rf byteseq-client byteseq-server