上一页 下一页

Orbit编程的基本方法

CORBA程序的工作流程

  • 定义你的对象和方法:使用IDL
  • Client调用你定义的对象方法
  • 调用被ORB传递到Server
  • Server真正调用你的方法
  • 结果沿原路返回
  • 工作流程的一些细节

    1. Server启动,等待来自Client的请求

    2. Client调用你定义的对象方法

    3. 调用的完成

    ORBit程序的编译

    其实问题比上面讲的还要复杂的多。为了在GNOME上编程,我们至少还需要了解stub和skeleton的概念。

  • stub:为了保证一个CORBA的实现是通用的,其接口是按IDL定义的CORBA对象,任何语言只要符合CORBA标准都能访问。因此C语言编写的Clients是无法直接访问的并调用某个远程对象的方法的。解决的办法就是在Client和ORB间加一个模块stub。stub的作用是把Client的请求转换为正确的标准的消息传递给ORB。它就象是远程对象在本地的一个代表或曰“代理”。这样才能使得对远地对象的操作就象在本地一样。
  • skeleton:skeleton的作用与stub相反,就是在对象所在地替Client完成调用。

    stub和skeleton的实现是程序员的事,但实际上这个工作大多数情况下是由IDL的编译器完成的。不同的语言需要使用不同的编译器。一个IDL的编译器甚至可以替程序员生成Servant的程序框架,而程序员只需填写自己的内容即可。

    举例说明

    echo-skels.c

    /*
     * This file was generated by orbit-idl - DO NOT EDIT!
     */
    
    #include 
    #include "echo.h"
    #define GET_ATOM(x) G_STMT_START{ GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->decoder(&x, (GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur), sizeof(x)); GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur = ((guchar *)GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur) + sizeof(x); }G_STMT_END
    
    void
    _ORBIT_skel_Echo_echoString(POA_Echo *_ORBIT_servant,
    GIOPRecvBuffer *_ORBIT_recv_buffer,
    CORBA_Environment *ev,
    void (*_impl_echoString)(PortableServer_Servant servant,
    const CORBA_char * input,
    CORBA_Environment *ev))
    {
      CORBA_char * input;
      GIOPSendBuffer *_ORBIT_send_buffer;
    
      if(giop_msg_conversion_needed(GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer))) {
    
    
      /* demarshal parameter input */
      {
        GIOP_unsigned_long len;
      GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur = ALIGN_ADDRESS(GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur, 4);
      GET_ATOM(len);
        input = len?(GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur):(((char *)GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur) - sizeof(CORBA_unsigned_long));    GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur = ((guchar *)GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur) + len;
      }
      } else {
    
    
      /* demarshal parameter input */
      {
        GIOP_unsigned_long len;
      GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur = ALIGN_ADDRESS(GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur, 4);
      len = *((CORBA_unsigned_long *)GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur);
      GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur = ((guchar *)GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur) + sizeof(CORBA_unsigned_long);
        input = len?(GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur):(((char *)GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur) - sizeof(CORBA_unsigned_long));    GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur = ((guchar *)GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur) + len;
      }
      }
    
    _impl_echoString(_ORBIT_servant, input,
     ev);
      _ORBIT_send_buffer = 
        giop_send_reply_buffer_use(GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer)->connection, NULL,
    	 _ORBIT_recv_buffer->message.u.request.request_id,
    	 ev->_major);
    
    if(ev->_major == CORBA_NO_EXCEPTION) {
    } else if(ev->_major == CORBA_SYSTEM_EXCEPTION)
     ORBit_send_system_exception(_ORBIT_send_buffer, ev);else if(ev->_major == CORBA_USER_EXCEPTION)
     ORBit_send_user_exception(_ORBIT_send_buffer, ev, NULL);  giop_send_buffer_write(_ORBIT_send_buffer);
      giop_send_buffer_unuse(_ORBIT_send_buffer);
    }
    
    static ORBitSkeleton get_skel_Echo(POA_Echo *servant,
    GIOPRecvBuffer *_ORBIT_recv_buffer,
    gpointer *impl)
    {
    gchar *opname = _ORBIT_recv_buffer->message.u.request.operation;
    
    switch(opname[0]) {
    case 'e':
    *impl = (gpointer)servant->vepv->Echo_epv->echoString;
    return (ORBitSkeleton)_ORBIT_skel_Echo_echoString;
    break;
    default: return NULL;
    }
    }
    
    static void init_local_objref_Echo(CORBA_Object obj, POA_Echo *servant)
    {
    obj->vepv[Echo__classid] = servant->vepv->Echo_epv;
    }
    void POA_Echo__init(POA_Echo *servant,
    CORBA_Environment *env)
    {
      static const PortableServer_ClassInfo class_info = {(ORBit_impl_finder)&get_skel_Echo, "IDL:Echo:1.0", (ORBit_local_objref_init)&init_local_objref_Echo};
      PortableServer_ServantBase__init(((PortableServer_ServantBase *)servant), env);
      ORBIT_OBJECT_KEY(servant->_private)->class_info = (PortableServer_ClassInfo*) &class_info;
    if(!Echo__classid)
    Echo__classid = ORBit_register_class(&class_info);
    }
    
    void POA_Echo__fini(POA_Echo *servant,
    CORBA_Environment *env)
    {
      PortableServer_ServantBase__fini(servant, env);
    }
    

    echo-stubs.c

    /*
     * This file was generated by orbit-idl - DO NOT EDIT!
     */
    
    #include 
    #include "echo.h"
    
    #define GET_ATOM(x) G_STMT_START{ GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->decoder(&x, (GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur), sizeof(x)); GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur = ((guchar *)GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur) + sizeof(x); }G_STMT_END
    void
    Echo_echoString(Echo _obj,
    const CORBA_char * input,
    CORBA_Environment *ev)
    {
    GIOP_unsigned_long _ORBIT_request_id;
    GIOPSendBuffer *_ORBIT_send_buffer;
    GIOPRecvBuffer *_ORBIT_recv_buffer;
    static const struct { CORBA_unsigned_long len; char opname[11]; } _ORBIT_operation_name_data = { 11, "echoString" };
    static const struct iovec _ORBIT_operation_vec = {(gpointer)&_ORBIT_operation_name_data, 15};
    GIOPConnection *_cnx;
    
    
    if(_obj->servant && _obj->vepv && Echo__classid)
    {
    ((POA_Echo__epv *)_obj->vepv[Echo__classid])->echoString(_obj->servant, input, ev);
    return;
    }
    _cnx = ORBit_object_get_connection(_obj);
    retry_request:
    _ORBIT_request_id = giop_get_request_id();
    if((_cnx == NULL) || (_obj->active_profile == NULL)) {
    CORBA_exception_set_system(ev, ex_CORBA_COMM_FAILURE, CORBA_COMPLETED_NO);
    return;
    }
    _ORBIT_send_buffer = 
    giop_send_request_buffer_use(_cnx, NULL,
    				  _ORBIT_request_id, CORBA_TRUE, &(_obj->active_profile->object_key_vec),
    				  &_ORBIT_operation_vec, &ORBit_default_principal_iovec);
    
    if(!_ORBIT_send_buffer) {
    CORBA_exception_set_system(ev, ex_CORBA_COMM_FAILURE, CORBA_COMPLETED_NO);
    return;
    }
    
    
      /* marshal parameter input */
      {
        GIOP_unsigned_long len = input?(strlen(input)+1):0;
    giop_message_buffer_do_alignment(GIOP_MESSAGE_BUFFER(_ORBIT_send_buffer), 4);
      giop_send_buffer_append_mem_indirect(GIOP_SEND_BUFFER(_ORBIT_send_buffer), &len, sizeof(len));
        if(input)
          giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(_ORBIT_send_buffer), input, len);
      }
    
    giop_send_buffer_write(_ORBIT_send_buffer);
    giop_send_buffer_unuse(_ORBIT_send_buffer);
    _ORBIT_recv_buffer = giop_recv_reply_buffer_use_2(ORBit_object_get_connection(_obj), _ORBIT_request_id, TRUE);
    if(_ORBIT_recv_buffer == NULL || _ORBIT_recv_buffer->message_buffer.message_header.message_type != GIOP_REPLY) {
    CORBA_exception_set_system(ev, ex_CORBA_COMM_FAILURE, CORBA_COMPLETED_MAYBE);
        if(_ORBIT_recv_buffer) giop_recv_buffer_unuse(_ORBIT_recv_buffer);
    return;
      }
    if(_ORBIT_recv_buffer->message.u.reply.reply_status != GIOP_NO_EXCEPTION) {
    if(_ORBIT_recv_buffer->message.u.reply.reply_status == GIOP_LOCATION_FORWARD) {
    if(_obj->forward_locations != NULL)
    ORBit_delete_profiles(_obj->forward_locations);
    _obj->forward_locations = ORBit_demarshal_IOR(_ORBIT_recv_buffer);
    _cnx = ORBit_object_get_forwarded_connection(_obj);
    giop_recv_buffer_unuse(_ORBIT_recv_buffer);
    
    goto retry_request;
    } else {
    ORBit_handle_exception(_ORBIT_recv_buffer, ev, NULL,_obj->orb);
    giop_recv_buffer_unuse(_ORBIT_recv_buffer);
    return;
      }
    }
      giop_recv_buffer_unuse(_ORBIT_recv_buffer);
      ev->_major = CORBA_NO_EXCEPTION;
    }
    
    
    
    在IDL编译器编译一个IDL文件时,同时生成一些头文件和必须的C文件,在用C编译器编译生成Client和Server的可执行程序时,需将这些文件同时编译链结。

    Makefile

    CC = gcc
    ORBIT_IDL = /usr/bin/orbit-idl
    ORBIT_CFLAGS = -I/usr/lib/glib/include -I/usr/include
    ORBIT_LIBS = -L/usr/lib -lORBit -lIIOP -lORBitutil -lglib -lnsl -lm
    CFLAGS = $(ORBIT_CFLAGS)
    LFLAGS = $(ORBIT_LIBS)
    
    all : idltargets echo-client echo-server
    
    echo-client : echo-client.o echo-common.o echo-stubs.o
    	$(CC) -o echo-client echo-client.o echo-stubs.o echo-common.o  -lIIOP -lORBit -lORBitutil $(LFLAGS)
    
    echo-server : echo-server.o echo-skels.o echo-common.o
    	$(CC) -o echo-server echo-server.o echo-skels.o echo-common.o  -lIIOP -lORBit -lORBitutil $(LFLAGS)
    
    
    clean : 
    	rm *.[oa] echo-client echo-server
    
    real-clean : clean
    	rm echo-stubs.[oc] echo-skels.[oc] echo.h echo-common.[oc]
     
    
    #
    # IDL compiler rules
    #
    
    # all in one shot
    
    idltargets : echo.idl
    	$(ORBIT_IDL) echo.idl
    
    # individual rules
    
    echo-stubs.c : echo.idl
    	$(ORBIT_IDL) echo.idl
    
    echo-common.c : echo.idl
    	$(ORBIT_IDL) echo.idl
    
    echo-skels.c : echo.idl
    	$(ORBIT_IDL) echo.idl
    
    echo-client.c : echo.h
    
    echo-server.c : echo.h
    
    echo.h : echo.idl
    	$(ORBIT_IDL) echo.idl
    
    

    上一页 下一页