CORBA回调函数在C#项目环境中的应用

来源:互联网 发布:淘宝照片拍摄设备 编辑:程序博客网 时间:2024/06/05 02:49

         哲学中有句话:存在就是真理。每种语言能在某个时期出现,并能在各个产品线广泛应用,说明它具有一定的生命力。

         如果选择不同的语言能解决我们的不同方案,难道不是我们所期望的理由?本文选择C#语言主要是使用C#开发WEB服务器,完成HTTP+XML数据通信。因项目对实时性没有苛刻性,换句话讲,如果实时性高也不会选择HTTP+XML

         本文的描述可以说是《IIOP.NETCORBA中间件应用技术》的一种扩展画面。以C#编写的Web服务器和CORBA中间件服务器结合体。

1、  场景描述

      

       计算机PC-2作为FEP服务器完成两项任务:

       任务1:处理从ISCS(综合监控)主动上传的格式数据(HTTP+XML),并解析成对应的模拟量和数字量。其中ISCSWeb服务器的客户端,主动与PC-2实现连接,Web服务器的端口号:8080。连接方式为长连接。

       任务2:把处理好的ISCS数据上传给PC-1,两者通讯方式以CORBA中间件实现。PC-2为中间件的服务端,PC-1为中间件的客户端。

         任务1和任务2之间以共享队列的方式完成数据交换。任务2发现队列中有未取走的数据,会主动通知(接口onNotify)计算机PC-1。其通知机制也就是我们要讲的CORBA回调函数。

2、  回调函数

         软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用、回调和异步调用。同步调用是一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用;回调是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口;异步调用是一种类似消息或事件的机制,不过它的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方(即调用客户方的接口)。回调和异步调用的关系非常紧密,通常我们使用回调来实现异步消息的注册,通过异步调用来实现消息的通知。同步调用是三者当中最简单的,而回调又常常是异步调用的基础。

         对于分布式组件代理体系CORBA,异步处理有多种方式,如回调接口、事件服务、通知服务等。事件服务和通知服务是CORBA用来处理异步消息的标准服务,他们主要负责消息的处理、派发、维护等工作。

         回调接口的原理很简单,CORBA客户和服务器都具有双重角色,即充当服务器也是客户客户。对一些简单的异步处理过程,我们可以通过回调机制来实现。

3、  CORBA接口文件定义

// **********************************************************************

//

// Copyright (c) 2013

// 2013.06.27

// liuxuezong, PSD, Shanghai, China

// All Rights Reserved

//

// **********************************************************************

#ifndef _RTSIPWEBSERVER_IDL_

#define _RTSIPWEBSERVER_IDL_

 

//

// version 1.0.0

//

 

module rtsip

{

  struct point_stream

  {

                string pointcode;

                octet type;

                float value;

  };

 

  typedef sequence <point_stream> PointStreamList;

 

  // This exception is raised every time a failure or error is

  // detected in a treatment.

  exception GeneralException

  {

                string error_msg;

  };

 

  interface EventHandler

  {

                void onNotify(in long changes);

  };

 

  interface FepManager

  {

                PointStreamList getPointsValue() raises(GeneralException);

 

                void setEventHandler(in EventHandler handler) raises(GeneralException);                    

  };

};

 

#endif

 

//

// EOF rtsipwebserver.idl

//

4C#实现部分

1)、FepManagerServer.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Runtime.Remoting.Channels;

using System.Runtime.Remoting;

using omg.org.CosNaming;

using Ch.Elca.Iiop;

using Ch.Elca.Iiop.Services;

using Ch.Elca.Iiop.Idl;

 

namespace FepWebService

{

    class FepManagerServer

    {

        private static FepManagerImpl fepmanager = null;

       

        public void run()

        {

            string nameServiceUrl ="corbaloc::localhost:10003/NameService";

            // register the channel

            int port = 10003;

            IiopChannel chan =newIiopChannel(port);

            ChannelServices.RegisterChannel(chan,false);

 

            fepmanager = new FepManagerImpl();

            string objectURI = "fepwebserver";

            RemotingServices.Marshal(fepmanager, objectURI);

 

            // publish the adder with an external name service

            NamingContext nameService = (NamingContext)RemotingServices.Connect(

                typeof(NamingContext), nameServiceUrl);

            NameComponent[] name =newNameComponent[] {newNameComponent("fepwebserver") };

            nameService.bind(name, fepmanager);

            Console.WriteLine("Fep web server running");

            Console.ReadLine();

 

            // unpublish with external name service

            nameService.unbind(name);

        }

 

        public bool isBindIiop()

        {

            return (fepmanager ==null ?false :true);

        }

 

        public void setQueue(PointQueue queue)

        {

            fepmanager.setQueue(queue);

        }

 

        public void onNotify(int changes)

        {

            fepmanager.onNotify(changes);

        }

    }

}

2)、FepManagerImpl.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using omg.org.CosNaming;

using Ch.Elca.Iiop;

using Ch.Elca.Iiop.Services;

using Ch.Elca.Iiop.Idl;

 

namespace FepWebService

{    

    ///<summary>

    /// the FepManagerImpl Implementation

    ///</summary>

    public class FepManagerImpl : MarshalByRefObject, rtsip.FepManager, rtsip.EventHandler

    {

        private static rtsip.EventHandler handler_;

        private static PointQueue queue_ = null;

 

        public override object InitializeLifetimeService()

        {

            // live forever

            return null;

        }

 

        public void setQueue(PointQueue queue)

        {

            queue_ = queue;

        }

 

        public rtsip.point_stream[] getPointsValue()

        {

            try

            {

                int nSize = queue_.GetCount();

                nSize = (nSize > 1024 ? 1024 : nSize);

                rtsip.point_stream[] points =new rtsip.point_stream[nSize];

                for (int i = 0; i < nSize; i++)

                {

                    rtsip.point_stream s =new rtsip.point_stream();

                    PointAttribute point = (PointAttribute)queue_.PopObj();

 

                    s.type = point.Type;

                    if (s.type ==PointAttribute.RTSIP_DATATYPE_DIGITAL)

                    {

                        s.value = Convert.ToByte(point.Value);

                    }

                    else

                    {

                        s.value = Convert.ToSingle(point.Value);

                    }

                    s.pointcode = point.PointCode;

                    points[i] = s;

                }

                return points;

            }

            catch (Exception e)

            {

                Console.WriteLine("exception: " + e);

            }

            return null;

        }

 

        public void setEventHandler(rtsip.EventHandler handler)

        {

            handler_ = handler;

        }

 

        public void onNotify(int changes)

        {

            try

            {

                if (handler_ != null && changes > 0)

                {

                    handler_.onNotify(changes);

                }

            }

            catch (Exception e)

            {

                Console.WriteLine("exception: " + e);

                handler_ = null;

            }

        }

    }

}

3)、PointQueue.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace FepWebService

{

    public struct PointAttribute

    {

        public const byte RTSIP_DATATYPE_NULL    = 0;

        public const byte RTSIP_DATATYPE_ANALOG  = 1;

        public const byte RTSIP_DATATYPE_DIGITAL = 2;

        public byte Type;

        public string PointCode;

        public string Value;

 

        public PointAttribute(byte type,string pointcode,string value)

        {

            this.Type = type;

            this.PointCode = pointcode;

            this.Value = value;

        }

    }

 

    public class PointQueue

    {

        #region Constants

 

        public const string ObjectType = "FepWebService.PointAttribute";     

 

        #endregion Constants

 

        private static RtsipQueue queue = new RtsipQueue();

 

        public void PushObj(Object obj)

        {

            queue.enqueue(obj);

        }          

 

        public Object PopObj()

        {

            return queue.dequeue();

        }

 

        public int GetCount()

        {

            return queue.getSize();

        }

    }

}

4)、RtsipQueue.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace FepWebService

{

    public class RtsipQueue

    {

        private static int QUEUE_MAX_LEN = 4096;

        private int m_nRead;

        private static int m_nWrite;

        private static Object[] data;

 

        public RtsipQueue()

        {

            data = new Object[QUEUE_MAX_LEN];

            m_nRead = 0;

            m_nWrite = 0;

        }

 

        public int getSize()

        {

            int num = (m_nWrite - m_nRead + QUEUE_MAX_LEN) % QUEUE_MAX_LEN;

            return num;

        }

 

        public Object dequeue()

        {

            if (m_nWrite == m_nRead)

            {

                return null;

            }

            Object obj = data[m_nRead];

            m_nRead = (m_nRead + 1) % QUEUE_MAX_LEN;

 

            return obj;

        }

 

        public void enqueue(Object obj)

        {

            int nWritep = m_nWrite;

            Object pData = data[nWritep];

            pData = null;

            data[nWritep] = obj;

            nWritep = (nWritep + 1) % QUEUE_MAX_LEN;

            m_nWrite = nWritep;

        }

    }

}

5)、Program.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using rtsip;

using FepWebService;

using HybridDSP.Net.HTTP;

using System.Xml;

using System.IO;

using System.Threading;

 

namespace FepWebService

{

    class RtsipHandler : IHTTPRequestHandler

    {      

        public static PointQueue queue = new PointQueue();

        public static FepManagerServer manager_ = null;

  

        public RtsipHandler(FepManagerServer manager)

        {

            manager_ = manager;

        }

 

        public void ParseXML(string PointCode, string strXML)

        {

            XmlDocument XDoc =newXmlDocument();

            XDoc.LoadXml(strXML);

            XmlNodeList nodelist = XDoc.SelectNodes("/vjournal/description");

            foreach (XmlNode nodein nodelist)

            {

                byte type = PointAttribute.RTSIP_DATATYPE_NULL;

                string strValue = node.InnerText;

                string strTemp = PointCode;

                strTemp.ToLower();

 

                if (strTemp.IndexOf("ai") > 0)

                {

                    type = PointAttribute.RTSIP_DATATYPE_ANALOG;

                }

                else if (strTemp.IndexOf("di") > 0)

                {

                    type = PointAttribute.RTSIP_DATATYPE_DIGITAL;

                }

                else

                {

                    type = PointAttribute.RTSIP_DATATYPE_DIGITAL;

                }

                PointAttribute point =newPointAttribute(type, PointCode, strValue);

                queue.PushObj(point);

            }

        }

 

        public void HandleRequest(HTTPServerRequest request,HTTPServerResponse response)

        {

            Stream body = request.GetRequestStream();

            long len = request.GetContentLength();

            if (len > 0)

            {

                byte[] b = new byte[len];

                body.Read(b, 0, Convert.ToInt32(len));

                string strBody = Encoding.ASCII.GetString(b);

                string strLocation = request.Get("content-location");

                Console.WriteLine("content-location:{0}", strLocation);

 

                int nIndex = strLocation.LastIndexOf("/") + 1;

                int nSize = strLocation.Length - nIndex;

                string PointCode = strLocation.Substring(nIndex, nSize);

 

                Console.WriteLine("Body:{0}", strBody);

 

                ParseXML(PointCode, strBody);

 

                // "HTTP/1.1 200 OK\r\nContent-Length:0\r\n\r\n"

                response.StatusAndReason = HTTPServerResponse.HTTPStatus.HTTP_OK;

                response.ContentLength = 0;

                response.Send();

            }

        }

        public static void ProcessXmlData()

        {

            while (true)

            {

                if (manager_ != null && manager_.isBindIiop())

                {

                    manager_.setQueue(queue);

                }      

                int nCount = queue.GetCount();

                if (manager_ != null && nCount > 0)

                {                   

                    manager_.onNotify(nCount);

                }              

                Thread.Sleep(50);

            }

        }

    }

 

    class RequestHandlerFactory : IHTTPRequestHandlerFactory

    {

        private static Thread _thread;

        private static FepManagerServer manager_ = null;

        public RequestHandlerFactory(FepManagerServer manager)

        {

            manager_ = manager;       

            _thread = new Thread(RtsipHandler.ProcessXmlData);

            _thread.Start();

        }

 

        public IHTTPRequestHandler CreateRequestHandler(HTTPServerRequest request)

        {

            RtsipHandler rtsipHandle =newRtsipHandler(manager_);

            return rtsipHandle;

        }

    }

 

    class Program

    {

        static void Main(string[] args)

        {

            FepManagerServer manager =newFepManagerServer();

            RequestHandlerFactory factory =newRequestHandlerFactory(manager);

            HTTPServer server =newHTTPServer(factory, 8080);           

            server.Start();

 

            manager.run();

 

            server.Stop();

        }

    }

}

5C++实现部分

         省略

6、结束语

         本文讲述了回调函数在CORBA中的使用情况,以C#工程典型的案例分析回调过程。远程函数调用结合回调函数功能,基本满足一般任务要求。 

原创粉丝点击