======================作为 ATL 开发人员使用 SOAP=============
ATL Server Web 服务为 C++ 开发人员提供了一个用本机代码创建和使用 Web 服务的简便方法。对于要在 Internet 上公开和使用 Web 服务的 C++ 开发人员来说,ATL Server 是首选方法。它已被设计为用于 Web 应用程序库(包括 SOAP 服务)的快速、轻量并具有高度灵活性的库。
ATL Server 之所以使用 ATL 作为名称,是因为它体现了 ATL 的高性能和高度灵活性的目标。例如,可以很容易地放弃 ATL Server HTTP 模型并编写自己的发送器,而同时仍然使用 ATL Server 封送/协议代码的优点。
ATL Server Web 服务使用类似于 COM 的语法来描述接口,这使当前的 ATL 开发人员易于学习。类似于 COM 的语法使开发人员可以轻松地将一个对象同时作为 COM 对象和 Web 服务公开。
属性的引入大大简化了代码,这对于非 ATL 开发人员来说同样简单得多。ATL Server 被设计为可以与其他所有 .NET Web 服务交互操作,这就便于开发人员在一个应用程序中使用多种技术。
这是 ATL Server 使您能够定义 Web 服务接口的方法。通过使用 C++ 属性、内联 IDL 属性和新的 __interface 关键字,ATL Server Web 服务接口极其类似于新的属性化版本的 COM 接口。这里是一个 Web 服务接口示例 IWeb_Service_ExampleService,它实现了一个方法,即 HelloWorld。HelloWorld 将 BSTR 用作输入并将 BSTR 作为输出返回。
请求处理程序。请求处理程序是一个 C++ 类,该类通过处理程序映射公开,并具有通过替换方法映射公开的方法。处理程序映射仅仅是文本标记和类名之间的映射,而方法映射只是文本标记和类中方法之间的映射。
[
request_handler(name="Default",sdl="GenWeb_Service_ExampleServiceSDL"),
soap_handler(
name="Web_Service_ExampleService",
namespace="urn:Web_Service_ExampleService",
protocol="soap"
)
]
class CWeb_Service_ExampleService:
public IWeb_Service_ExampleService
{
public:
HTTP 请求进入 IIS,然后 IIS 根据 URL 和扩展名将请求映射到适当的 ISAPI DLL。接下来,ISAPI DLL 将请求中指定的处理程序(处理程序在标记或查询参数中指定)映射到适当的应用程序 DLL。应用程序 DLL 将此处理程序映射到 C++ 对象。在此模型(即 ATL Server 模型)中,Web 应用程序和 Web 服务之间的唯一区别就在于这最后一个步骤。在 Web 服务中,C++ 对象能够对 SOAP 进行解码/编码(执行此操作的代码由编译器在分析 soap_handler 属性时插入)。
您可以看到我们的类是从我们的接口继承的,并且使用了 [soap_method] 属性来指示 HelloWorld 方法将处理 SOAP 请求。同实现其他任何 C++ 方法一样实现此方法。
soap_handler 属性还确保自动生成描述服务的有效 WSDL。此服务描述(其格式为 XML/WSDL)由 Web 服务的使用者使用以确保他们以正确的格式发送/接收正确的数据。
通过 ATL Server 使用 Web 服务
通过 ATL Server 使用 Web 服务同样是一个比较简单的操作。开发人员使用“添加 Web 引用”对话框,然后使其指向 .disco 文件,该文件又指向 WSDL,其方法与使用任何其他类型的 Web 引用相同。该对话框在后台运行 Web 服务的 WSDL 上的 sproxy.exe 实用工具(对于非本机 .NET Web 服务来说使用的是另一种实用工具)。
此操作将创建 Web 服务代理文件,该文件包含使用所请求的 Web服务所需的所有 C++ 代码。使用 WSDL 中的信息,代理生成器可以计算出 Web 服务期望接收到的和将返回到客户端的信息。然后就使代理生成器可以创建能够与 Web 服务“对话”的头文件。
namespace Zap
{
// Define the event arguments
public class GreetingEventArgs : EventArgs
{
public GreetingEventArgs(string greeting)
{
this.greeting = greeting;
}
public string greeting;
}
// Define the event
public delegate void GreetingEvent(object sender,
GreetingEventArgs e);
// Define the Service
public class Waz : MarshalByRefObject
{
// The client will subscribe and
// unsubscribe to this event
public event GreetingEvent Greeting;
// Method called remotely by client
public void HelloMethod(string greeting)
{
Console.WriteLine("Received String {0}", greeting);
// Package String in GreetingEventArgs
GreetingEventArgs e = new GreetingEventArgs(greeting);
// Fire Event
if (Greeting != null)
{
Greeting(this, e);
}
}
}
}
host.cs
using System;
using System.IO;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels.HTTP;
public class Host
{
public static void Main(string[] args)
{
// Manually load the http channel.
// This could also be done in the remoting configuration file.
ChannelServices.RegisterChannel(new HTTPChannel(999));
// Register the wellknown server type.
// This could also done in the remoting configuration file.
RemotingServices.RegisterWellKnownType(
"Zap", // Assembly
"Zap.Waz", // Full type name
"host/Waz.soap", // URI
WellKnownObjectMode.Singleton); // Object Mode
// We are done, wait until the user wants to exit
Console.WriteLine("Host is ready to process remote messages.");
Console.WriteLine("Press ENTER to exit");
String keyState = Console.ReadLine();
}
}
客户端
client.cs
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels.HTTP;
using Zap;
// Local Marshal by Ref Object onto which
// the event will be fired
public class Baz : MarshalByRefObject
{
public void GreetingHandler(object sender, GreetingEventArgs e)
{
Console.WriteLine("GreetingHandler callback : Greeting : {0}\n",
e.greeting);
}
}
public class Client
{
public static void Main(String[] args)
{
Baz baz = new Baz();
// This could also be done with a Remoting configuration file
// Registe the HTTP Channel
ChannelServices.RegisterChannel(new HTTPChannel(0));
// Obtain a Proxy to the SOAP URL
Waz waz = (Waz)Activator.GetObject(
typeof(Waz),
"http://localhost:999/host/Waz.soap"
);
// Subscribe to event : occurs over SOAP
waz.Greeting += new GreetingEvent(baz.GreetingHandler);
for (int i = 0; i < 5; i++)
{
// Occurs over SOAP to waz)
waz.HelloMethod("Bill" + " " + i);
}
// Unsubscribe to event : occurs over SOAP
waz.Greeting -= new GreetingEvent(baz.GreetingHandler);
}
}