Using Web Services for Remoting over the Internet. (下)

services|web

  • Decoding and de-serializing of the request message
  • Invoking the Remote Method
  • Encoding and serialization of the response message

[WebMethod]
public string SyncProcessMessage(string request)
{
   // Request: decoding and deserializing
   byte[] reqbyteArray = Convert.FromBase64String(request);
   MemoryStream reqstream = new MemoryStream();
   reqstream.Write(reqbyteArray, 0, reqbyteArray.Length);
   reqstream.Position = 0;
   BinaryFormatter bf = new BinaryFormatter();
   IMessage reqmsg = (IMessage)bf.Deserialize(reqstream);
   reqmsg.Properties["__Uri"] = reqmsg.Properties["__Uri2"]; // work around!!
   reqstream.Close();

   // Action: invoke the Remote Method
   string[] stype = reqmsg.Properties["__TypeName"].ToString().Split(new Char[]{','}); // split typename
   Assembly asm = Assembly.Load(stype[1].TrimStart(new char[]{' '})); // load type of the remote object
   Type objectType = asm.GetType(stype[0]);                           // type
   string objectUrl = reqmsg.Properties["__Uri"].ToString();          // endpoint
   object ro = RemotingServices.Connect(objectType, objectUrl);       // create proxy
   TraceIMessage(reqmsg);
   IMessage rspmsg = RemotingServices.ExecuteMessage((MarshalByRefObject)ro,
                                                     (IMethodCallMessage)reqmsg);
   TraceIMessage(rspmsg);

   // Response: encoding and serializing
   MemoryStream rspstream = new MemoryStream();
   bf.Serialize(rspstream, rspmsg);
   rspstream.Position = 0;
   string response = Convert.ToBase64String(rspstream.ToArray());
   rspstream.Close();

   return response;
}

[WebMethod]
public string SyncProcessSoapMessage(string request)
{
   IMessage retMsg = null;
   string response;

   try
   {
      Trace.WriteLine(request);

      // Request: deserialize string into the SoapMessage
      SoapFormatter sf = new SoapFormatter();
      sf.TopObject = new SoapMessage();
      StreamWriter rspsw = new StreamWriter(new MemoryStream());
      rspsw.Write(request);
      rspsw.Flush();
      rspsw.BaseStream.Position = 0;
      ISoapMessage soapmsg = (ISoapMessage)sf.Deserialize(rspsw.BaseStream);
      rspsw.Close();

      // Action: invoke the Remote Method
      object[] values = soapmsg.ParamValues;
      string[] stype = values[2].ToString().Split(new Char[]{','});
      Assembly asm = Assembly.Load(stype[1].TrimStart(new char[]{' '}));
      Type objectType = asm.GetType(stype[0]);
      string objectUrl = values[0].ToString();
      RealProxyWrapper rpw = new RealProxyWrapper(objectType, objectUrl,
                                                  soapmsg.ParamValues[4]);
      object ro = rpw.GetTransparentProxy();
      MethodInfo mi = objectType.GetMethod(values[1].ToString());
      object retval = mi.Invoke(ro, values[3] as object[]);
      retMsg = rpw.ReturnMessage;
   }
   catch(Exception ex)
   {
      retMsg = new ReturnMessage((ex.InnerException == null) ?
                                           ex : ex.InnerException, null);
   }
   finally
   {
      // Response: serialize IMessage into string
      Stream rspstream = new MemoryStream();
      SoapFormatter sf = new SoapFormatter();
      RemotingSurrogateSelector rss = new RemotingSurrogateSelector();
      rss.SetRootObject(retMsg);
      sf.SurrogateSelector = rss;
      sf.AssemblyFormat = FormatterAssemblyStyle.Full;
      sf.TypeFormat = FormatterTypeStyle.TypesAlways;
      sf.TopObject = new SoapMessage();
      sf.Serialize(rspstream, retMsg);
      rspstream.Position = 0;
      StreamReader sr = new StreamReader(rspstream);
      response = sr.ReadToEnd();
      rspstream.Close();
      sr.Close();
   }

   Trace.WriteLine(response);
   return response;
}
The implementation of the steps are depended from the type of formatter such as SoapFormatter or BinaryFormatter. The first and last steps are straightforward using the Remoting namespace classes. The second one (action) for the SoapFormatter message needed to create the following class to obtain IMessage of the MethodCall:
public class RealProxyWrapper : RealProxy
{
   string _url;
   string _objectURI;
   IMessageSink _messageSink;
   IMessage _msgRsp;
   LogicalCallContext _lcc;

   public IMessage ReturnMessage { get { return _msgRsp; }}
   public RealProxyWrapper(Type type, string url, object lcc) : base(type)
   {
      _url = url;
      _lcc = lcc as LogicalCallContext;

      foreach(IChannel channel in ChannelServices.RegisteredChannels)
      {
         if(channel is IChannelSender)
         {
            IChannelSender channelSender = (IChannelSender)channel;
            _messageSink = channelSender.CreateMessageSink(_url, null, out _objectURI);
            if(_messageSink != null)
               break;
         }
      }

      if(_messageSink == null)
      {
         throw new Exception("A supported channel could not be found for url:"+ _url);
      }
   }
   public override IMessage Invoke(IMessage msg)
   {
      msg.Properties["__Uri"] = _url; // endpoint
      msg.Properties["__CallContext"] = _lcc; // caller's callcontext
      _msgRsp = _messageSink.SyncProcessMessage(msg);

      return _msgRsp;
   }
}// RealProxyWrapper
Test
I built the following package to test functionality of the WebServiceListener and WebServiceChannelLib assemblies. Note that this package has only test purpose. Here is what you downloaded it:

  • ConsoleClient, the test console program to invoke the call over Internet - client machine
  • ConsoleServer, the host process of the MyRemoteObject - server machine
  • MyRemoteObject, the remote object - server machine
  • WebServiceChannelLib, the custom client channel
  • WebServiceListener, the Web Service listener  - server machine

To recompile a package and its deploying in your environment follow these notes:

  • The folder WebServiceListener has to be moved to the virtual directory (inetpub\wwwroot).
  • The MyRemoteObject assembly has to be install into the GAC on  the server machine
  • The WebServiceChannelLib assembly has to be install into the GAC on the client machine
  • (option) The MSMQChannelLib assembly [1] has to be install into the GAC on the server machine
  • The solution can be tested also using the same machine (Win2k/Adv Server)
  • Use the Echo WebMethod on the test page of the WebServiceListener to be sure that this service will be work  

The test case is very simple. First step is to launch the ConsoleServer program. Secondly open the ConsoleClient program and follow its prompt text. If everything is going right you will see a response from the remote object over Internet. I am recommending to make a first test on the same machine and then deploying over Internet.
Conclusion
In this article has been shown one simple way how to implement a solution for remoting over Internet. I used the power of .Net Technologies such as SOAP, Remoting, Reflection and Web Service. The advantage of this solution is a full transparency between the consumer and remote object. This logical connectivity can be mapped into the physical path using the config files, which they can be administratively changed.
 

时间: 2024-09-13 09:33:54

Using Web Services for Remoting over the Internet. (下)的相关文章

Using Web Services for Remoting over the Internet.

Introduction This article describes a design and implementation (C#) of the Remoting over Internet using the Web Service as a gateway into the Remoting infrastructure. The Web Service Gateway (Custom Remoting Channel) allows to enhance the remoting c

vs.net中web services入门

services|web services 入门摘要:Microsoft Visual Studio .NET 和 XML Web services 提供了一个简单.灵活且基于标准的模型,开发人员无论使用何种平台.编程语言或对象模型均可以编写组合应用程序.本文将帮助您快速学习使用 Visual Studio .NET 创建并访问 XML Web services.本文包含一些指向英文站点的链接. 目录简介 用托管代码编写的 XML Web services 使用 Visual Studio 创建

WEB SERVICES状态管理

services|web WEB SERVICES状态管理 在默认情况下,.NET下的WEB SERVICES是无状态的.不过可以用ASP.NET提供的状态管理那就是SESSION和APPLICATION.这使得WEB SERVICES下状态管理变得简单了,只需使用WEBMETHOD属性的ENABLESESSION子属性就可[WEBMETHOD(ENABLESESSION=TRUE)] 服务端代码如下:[WebMethod(EnableSession= true)] public client

COM+ Web 服务:通过复选框路由到 XML Web Services(1) (微软中国)

services|web|xml|复选框|微软 COM+ Web 服务:通过复选框路由到 XML Web Services John Noss 和 Jonathan HawkinsMicrosoft Corporation 2001年11月 摘要:COM+ Web 服务新增了某些功能,可与 Microsoft .NET Remoting 集成,并通过 SOAP for COM+ 组件实现 XML Web Services 发布的复选框激活.本文通过几个示例介绍基本的互操作性.配置以及托管和非托管

COM+ Web 服务:通过复选框路由到 XML Web Services (转)

services|web|xml|复选框 COM+ Web 服务:通过复选框路由到 XML Web Services John Noss 和 Jonathan HawkinsMicrosoft Corporation 2001年11月 摘要:COM+ Web 服务新增了某些功能,可与 Microsoft .NET Remoting 集成,并通过 SOAP for COM+ 组件实现 XML Web Services 发布的复选框激活.本文通过几个示例介绍基本的互操作性.配置以及托管和非托管 CO

COM+ Web 服务:通过复选框路由到 XML Web Services (转)3

services|web|xml|复选框 现在,应用程序已发布为 XML Web Services,并且可以使用 SOAP 激活.使用 Internet Explorer 浏览到 http://localhost/VB6Soap/default.aspx,您会在该 aspx 页上发现一个超链接,通过它可以链接到您的组件所生成的 WSDL.以下 VBScript 将激活您的组件: set c = GetObject   ("soap:wsdl=http://localhost/VB6Soap/VB

Web Services是什么?

services|web Web Services突然热起来了,特别是M$.net为我们描述了一个互联共享的世界,其实这些美好前景当初在Java诞生时早已经憧憬过,但理想的实现过程总是崎岖漫长. 我们从一个应用看看Web Services是怎么运作的: 有一个咖啡连锁店的老板叫Coffee Break,要拓展自己销售的咖啡品种,他指示他的采购经理去寻找一些新的咖啡提供商,得到他们的咖啡全部价格,并且在需要时能够立即下订单,Coffee Break能够分析他们的价格,并决定选用哪一种咖啡,从哪个公

Web Services和其他的技术的比较

services|web|比较   XMLHTTP与SOAP:    XML是web serivces的核心基础技术,是SOAP实现的关键所在:而XMLHTTP就是根据XML来设计的.从实现的方式上讲:XMLHTTP是基于浏览器的,只要有IE,就能实现向服务器传递XML字符串,具有很高的通用性.但是浏览器不是用来做XMLHTTP,它是面向大众用户浏览的,如果能用XML完成各种操作,必然会影响到用户.比如以前版本的msxml的对应浏览器,是可以访问客户端XML文档(初始时为XMLHTTP设计的),

Web Services的简单介绍

services|web Web Services 是网格服务的基础, 也是OGSA和IOGSI的奠基石(GT3). 理解WebService的架构是使用GT3,编写网格服务的基础. 最近 有很多关于"Web Services"的议论并且许多公司也开始为他们的企业应用作出反应.那么,Web Services究竟是什么?简单的说,他们是另一个分布计算技术(像CORBA, RMI, EJB等等),容许我们创建客户端/服务端应用. 举个例子,让我们假设我不得不为一个连锁店开发一个程序.这家连