1. Trang chủ
  2. » Công Nghệ Thông Tin

Developer’s Guide Borland Delphi 7 for Windows PHẦN 9 pptx

111 878 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 111
Dung lượng 601,79 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Specify the URL by setting the URL property to the location of the server: X.URL := 'http://www.myco.com/MyService.dll/SOAP/IServerInterface'; • If you want to look up the URL, namespac

Trang 1

Defining and using SOAP headers

The SOAP encoding of a request to your Web Service application and of the response your application sends include a set of header nodes Some of these, such as the SOAP Action header, are generated and interpreted automatically However, you can also define your own headers to customize the communication between your server and its clients Typically, these headers contain information that is associated with the entire invokable interface, or even with the entire application, rather than just the method that is the subject of a single message

Defining header classes

For each header you want to define, create a descendant of TSOAPHeader

TSOAPHeader is a descendant of TRemotable That is, SOAP header objects are simply

special types of remotable objects As with any remotable object, you can add

published properties to your TSOAPHeader descendant to represent the information

that your header communicates Once you have defined a SOAP header class, it must

be registered with the remotable type registry For more information about remotable objects, see “Using remotable objects” on page 38-6 Note that unlike other remotable classes, which are registered automatically when you register an invokable interface that uses them, you must explicitly write code to register your header types

TSOAPHeader defines two properties that are used to represent attributes of the

SOAP header node These are MustUnderstand and Actor When the MustUnderstand attribute is True, the recipient of a message that includes the header is required to recognize it If the recipient can’t interpret a header with the MustUnderstand

attribute, it must abort the interpretation of the entire message An application can

safely ignore any headers it does not recognize if their MustUnderstand attribute is not set The use of MustUnderstand is qualified by the Actor property Actor is a URI

that identifies the application to which the header is directed Thus, for example, if your Web Service application forwards requests on to another service for further processing, some of the headers in client messages may be targeted at that other

service If such a header includes the MustUnderstand attribute, you should not abort

the request even if your application can’t understand the header Your application is

only concerned with those headers that give its URL as the Actor.

Sending and receiving headers

Once you have defined and registered header classes, they are available for your application to use When your application receives a request, the headers on that

message are automatically converted into the corresponding TSOAPHeader

descendants that you have defined Your application identifies the appropriate header class by matching the name of the header node against the type name you used when you registered the header class Any headers for which it can’t find a

match in the remotable type registry are ignored (or, if their MustUnderstand attribute

is True, the application generates a SOAP fault).

You can access the headers your application receives using the ISOAPHeaders

Trang 2

Use the Get method of ISOAPHeaders to access the headers by name For example:

TServiceImpl.GetQuote(Symbol: string): Double;

var

Headers: ISOAPHeaers;

H: TAuthHeader;

begin

Headers := Self as ISOAPHeaders;

Headers.Get(AuthHeader, TSOAPHeader(H)); { Retrieve the authentication header }

try

if H = nil then

raise ERemotableException.Create('SOAP header for authentication required');

{ code here to check name and password }

If you want to include any headers in the response your application generates to a

request message, you can use the same interface ISOAPHeaders defines a Send

method to add headers to the outgoing response Simply create an instance of each header class that corresponds to a header you want to send, set its properties, and

Headers := Self as ISOAPHeaders;

{ code to lookup the quote and set the return value }

{ this code sets the Delay variable to the time delay on the quote }

Handling scalar-type headers

Some Web Services define and use headers that are simple types (such as an integer

or string) rather than a complex structure that corresponds to a remotable type

However, Delphi’s support for SOAP headers requires that you use a TSOAPHeader

descendant to represent header types You can define header classes for simple types

by treating the TSOAPHeader class as a holder class That is, the TSOAPHeader

descendant has a single published property, which is the type of the actual header

To signal that the SOAP representation does not need to include a node for the

TSOAPHeader descendant, call the remotable type registry’s RegisterSerializeOptions

method (after registering the header type) and give your header type an option of

xoSimpleTypeWrapper.

Trang 3

Communicating the structure of your headers to other applications

If your application defines headers, you need to allow its clients to access those definitions If those clients are also written in Delphi, you can share the unit that defines and registers your header classes with the client application However, you may want to let other clients know about the headers you use as well To enable your application to export information about its header classes, you must register them with the invocation registry

Like the code that registers your invokable interface, the code to register a header class for export is added to the initialization section of the unit in which it is defined

Use the global InvRegistry function to obtain a reference to the invocation registry and call its RegisterHeaderClass method, indicating the interface with which the

header is associated:

initialization

InvRegistry.RegisterInterface(TypeInfo(IMyWebService)); {register the interface}

InvRegistry.RegisterHeaderClass(TypeInfo(IMyWebService), TMyHeaderClass); {and the header}

end.

You can limit the header to a subset of the methods on the interface by subsequent

calls to the RegisterHeaderMethod method.

Note The implementation section’s uses clause must include the InvokeRegistry unit so

that the call to the InvRegistry function is defined.

Once you have registered your header class with the invocation registry, its

description is added to WSDL documents when you publish your Web Service For information about publishing Web Services, see “Generating WSDL documents for a Web Service application” on page 38-19

Note This registration of your header class with the invocation registry is in addition to the registration of that class with the remotable type registry

Creating custom exception classes for Web Services

When your Web Service application raises an exception in the course of trying to execute a SOAP request, it automatically encodes information about that exception in

a SOAP fault packet, which it returns instead of the results of the method call The client application then raises the exception

By default, the client application raises a generic exception of type

ERemotableExceptionwith the information from the SOAP fault packet You can

transmit additional, application-specific information by deriving an

ERemotableException descendant The values of any published properties you add to

the exception class are included in the SOAP fault packet so that the client can raise

Trang 4

If the client also defines and registers your ERemotableException descendant, then

when it receives the SOAP fault packet, it automatically raises an instance of the appropriate exception class, with all properties set to the values in the SOAP fault packet

To allow clients to import information about your ERemotableException descendant,

you must register it with the invocation registry as well as the remotable type

registry Add a call to the RegisterException method of the object that the global

InvRegistry function returns.

Generating WSDL documents for a Web Service application

To allow client applications to know what Web Services your application makes available, you can publish a WSDL document that describes your invokable

interfaces and indicates how to call them

To publish a WSDL document that describes your Web Service, include a

TWSDLHTMLPublish component in your Web Module (The SOAP Server

Application wizard adds this component by default.) TWSDLHTMLPublish is an

auto-dispatching component, which means it automatically responds to incoming messages that request a list of WSDL documents for your Web Service Use the

WebDispatch property to specify the path information of the URL that clients must

use to access the list of WSDL documents The Web browser can then request the list

of WSDL documents by specifying an URL that is made up of the location of the

server application followed by the path in the WebDispatch property This URL looks

something like the following:

http://www.myco.com/MyService.dll/WSDL

Tip If you want to use a physical WSDL file instead, you can display the WSDL

document in your Web browser and then save it to generate a WSDL document file

Note In addition to the WSDL document, the THWSDLHTMLPublish also generates a

WS-Inspection document to describe the service for automated tools The URL for this document looks something like the following:

http://www.myco.com/MyService.dll/inspection.wsil

It is not necessary to publish the WSDL document from the same application that implements your Web Service To create an application that simply publishes the WSDL document, omit the code that implements and registers the implementation objects and only include the code that defines and registers invokable interfaces, remotable classes that represent complex types, and any remotable exceptions

By default, when you publish a WSDL document, it indicates that the services are available at the same URL as the one where you published the WSDL document (but with a different path) If you are deploying multiple versions of your Web Service application, or if you are publishing the WSDL document from a different

application than the one that implements the Web Service, you will need to change the WSDL document so that it includes updated information on where to locate the Web Service

Trang 5

To change the URL, use the WSDL administrator The first step is to enable the

administrator You do this by setting the AdminEnabled property of the

TWSDLHTMLPublish component to true Then, when you use your browser to

display the list of WSDL documents, it includes a button to administer them as well Use the WSDL administrator to specify the locations (URLs) where you have

deployed your Web Service application

Writing clients for Web Services

You can write clients that access Web Services that you have written, or any other Web Service that is defined in a WSDL document There are three steps to writing an application that is the client of a Web Service:

• Importing the definitions from a WSDL document

• Obtaining an invokable interface and calling it to invoke the Web Service

• Processing the headers of the SOAP messages that pass between the client and the server

Importing WSDL documents

Before you can use a Web Service, your application must define and register the invokable interfaces and types that are included in the Web Service application To obtain these definitions, you can import a WSDL document (or XML file) that defines the service The WSDL importer creates a unit that defines and registers the

interfaces, headers, and types you need to use For details on using the WSDL importer, see “Using the WSDL importer” on page 38-13

Calling invokable interfaces

To call an invokable interface, your client application must include any definitions of the invokable interfaces and any remotable classes that implement complex types

If the server is written in Delphi, you can use the same units that the server

application uses to define and register these interfaces and classes instead of the files generated by importing a WSDL file Be sure that the unit uses the same namespace URI and SOAPAction header when it registers invokable interfaces These values can

be explicitly specified in the code that registers the interfaces, or it can be

automatically generated If it is automatically generated, the unit that defines the interfaces must have the same name in both client and server, and both client and

server must define the global AppNameSpacePrefix variable to have the same value

Once you have the definition of the invokable interface, there are two ways you can obtain an instance to call:

• If you imported a WSDL document, the importer automatically generates a global

Trang 6

Obtaining an invokable interface from the generated function

The WSDL importer automatically generates a function from which you can obtain the invokable interfaces you imported For example, if you imported a WSDL

document that defined an invokable interface named IServerInterface, the generated

unit would include the following global function:

function GetIServerInterface(UseWSDL: Boolean; Addr: string): IServerInterface;

The generated function takes two parameters: UseWSDL and Addr UseWSDL

indicates whether to look up the location of the server from a WSDL document (true),

or whether the client application supplies the URL for the server (false)

When UseWSDL is false, Addr is the URL for the Web Service When UseWSDL is true, Addr is the URL of a WSDL document that describes the Web Service you are

calling If you supply an empty string, this defaults to the document you imported This second approach is best if you expect that the URL for the Web Service may change, or that details such as the namespace or SOAP Action header may change Using this second approach, this information is looked up dynamically at the time your application makes the method call

Note The generated function uses an internal remote interfaced object to implement the invokable interface If you are using this function and find you need to access that

underlying remote interfaced object, you can obtain an IRIOAccess interface from the

invokable interface, and use that to access the remote interfaced object:

Using a remote interfaced object

If you do not use the global function to obtain the invokable interface you want to

call, you can create an instance of THTTPRio for the desired interface:

X := THTTPRio.Create(nil);

Note It is important that you do not explicitly destroy the THTTPRio instance If it is created without an Owner (as in the previous line of code), it automatically frees itself when its interface is released If it is created with an Owner, the Owner is responsible for freeing the THTTPRio instance.

Trang 7

Once you have an instance of THTTPRio, provide it with the information it needs to

identify the server interface and locate the server There are two ways to supply this information:

• If you do not expect the URL for the Web Service or the namespaces and soap Action headers it requires to change, you can simply specify the URL for the Web

Service you want to access THTTPRio uses this URL to look up the definition of

the interface, plus any namespace and header information, based on the

information in the invocation registry Specify the URL by setting the URL

property to the location of the server:

X.URL := 'http://www.myco.com/MyService.dll/SOAP/IServerInterface';

• If you want to look up the URL, namespace, or Soap Action header from the

WSDL document dynamically at runtime, you can use the WSDLLocation, Service, and Port properties, and it will extract the necessary information from the WSDL

document:

X.WSDLLocation := 'Cryptography.wsdl';

X.Service := 'Cryptography';

X.Port := 'SoapEncodeDecode';

After specifying how to locate the server and identify the interface, you can obtain an

interface pointer for the invokable interface from the THTTPRio object You obtain this interface pointer using the as operator Simply cast the THTTPRio instance to the

invokable interface:

InterfaceVariable := X as IEncodeDecode;

Code := InterfaceVariable.EncodeValue(5);

When you obtain the interface pointer, THTTPRio creates a vtable for the associated

interface dynamically in memory, enabling you to make interface calls

THTTPRio relies on the invocation registry to obtain information about the invokable

interface If the client application does not have an invocation registry, or if the

invokable interface is not registered, THTTPRio can’t build its in-memory vtable.

Warning If you assign the interface you obtain from THTTPRio to a global variable, you must

change that assignment to nil before shutting down your application For example, if

InterfaceVariable in the previous code sample is a global variable, rather than stack

variable, you must release the interface before the THTTPRio object is freed

Typically, this code goes in the OnDestroy event handler of the form or data module:

procedure TForm1.FormDestroy(Sender: TObject);

begin

InterfaceVariable := nil;

end;

The reason you must reassign a global interface variable to nil is because THTTPRio

builds its vtable dynamically in memory That vtable must still be present when the interface is released If you do not release the interface along with the form or data module, it is released when the global variable is freed on shutdown The memory for global variables may be freed after the form or data module that contains the

THTTPRio object, in which case the vtable will not be available when the interface is

Trang 8

Processing headers in client applications

If the Web Service application you are calling expects your client to include any headers in its requests or if its response messages include special headers, your client application needs the definitions of the header classes that correspond to these headers When you import a WSDL document that describes the Web Service application, the importer automatically generates code to declare these header classes and register them with the remotable type registry If the server is written in Delphi, you can use the same units that the server application uses to define and register these header classes instead of the files generated by importing a WSDL file

Be sure that the unit uses the same namespace URI and SOAPAction header when it registers invokable interfaces These values can be explicitly specified in the code that registers the interfaces, or it can be automatically generated If it is automatically generated, the unit that defines the interfaces must have the same name in both client

and server, and both client and server must define the global AppSpacePrefix variable

to have the same value

Note For more information about header classes, see “Defining and using SOAP headers”

on page 38-16

As with a server, client applications use the ISOAPHeaders interface to access

incoming headers and add outgoing headers The remote interfaced object that you

use to call invokable interfaces implements the ISOAPHeaders interface However, you can’t obtain an ISOAPHeaders interface directly from the remote interfaced

object This is because when you try to obtain an interface directly from a remote interfaced object, it generates an in-memory vtable, assuming that the interface is an

invokable interface Thus, you must obtain the ISOAPHeaders interface from the

invokable interface rather than from the remote interfaced object:

(Service as ISOAPHeaders).Send(Hdr); { add the header to outgoing message }

Val := Service.GetQuote('BORL'); { invoke the service }

finally

Hdr.Free;

end;

end;

Trang 10

C h a p t e r

39

This chapter describes the socket components that let you create an application that can communicate with other systems using TCP/IP and related protocols Using sockets, you can read and write over connections to other machines without

worrying about the details of the underlying networking software Sockets provide connections based on the TCP/IP protocol, but are sufficiently general to work with related protocols such as User Datagram Protocol (UDP), Xerox Network System (XNS), Digital’s DECnet, or Novell’s IPX/SPX family

Using sockets, you can write network servers or client applications that read from and write to other systems A server or client application is usually dedicated to a single service such as Hypertext Transfer Protocol (HTTP) or File Transfer Protocol (FTP) Using server sockets, an application that provides one of these services can link to client applications that want to use that service Client sockets allow an application that uses one of these services to link to server applications that provide the service

Implementing services

Sockets provide one of the pieces you need to write network servers or client

applications For many services, such as HTTP or FTP, third party servers are readily available Some are even bundled with the operating system, so that there is no need

to write one yourself However, when you want more control over the way the service is implemented, a tighter integration between your application and the network communication, or when no server is available for the particular service you need, then you may want to create your own server or client application For

example, when working with distributed data sets, you may want to write a layer to communicate with databases on other systems

Trang 11

Understanding service protocols

Before you can write a network server or client, you must understand the service that your application is providing or using Many services have standard protocols that your network application must support If you are writing a network application for

a standard service such as HTTP, FTP, or even finger or time, you must first

understand the protocols used to communicate with other systems See the

documentation on the particular service you are providing or using

If you are providing a new service for an application that communicates with other systems, the first step is designing the communication protocol for the servers and clients of this service What messages are sent? How are these messages coordinated? How is the information encoded?

Communicating with applications

Often, your network server or client application provides a layer between the networking software and an application that uses the service For example, an HTTP server sits between the Internet and a Web server application that provides content and responds to HTTP request messages

Sockets provide the interface between your network server or client application and the networking software You must provide the interface between your application and the clients that use it You can copy the API of a standard third party server (such

as Apache), or you can design and publish your own API

Services and ports

Most standard services are associated, by convention, with specific port numbers We will discuss port numbers in greater detail later For now, consider the port number a numeric code for the service

If you are implementing a standard service for use in cross-platform applications, Linux socket objects provide methods for you to look up the port number for the service If you are providing a new service, you can specify the associated port

number in the /etc/services file (or its equivalent for your particular Linux

distribution) See your Linux documentation for more information

Trang 12

Types of socket connections

Socket connections can be divided into three basic types, which reflect how the connection was initiated and what the local socket is connected to These are

• Client connections

• Listening connections

• Server connections

Once the connection to a client socket is completed, the server connection is

indistinguishable from a client connection Both end points have the same

capabilities and receive the same types of events Only the listening connection is fundamentally different, as it has only a single endpoint

Client connections

Client connections connect a client socket on the local system to a server socket on a remote system Client connections are initiated by the client socket First, the client socket must describe the server socket to which it wishes to connect The client socket then looks up the server socket and, when it locates the server, requests a connection The server socket may not complete the connection right away Server sockets maintain a queue of client requests, and complete connections as they find time When the server socket accepts the client connection, it sends the client socket a full description of the server socket to which it is connecting, and the connection is completed by the client

Listening connections

Server sockets do not locate clients Instead, they form passive “half connections” that listen for client requests Server sockets associate a queue with their listening connections; the queue records client connection requests as they come in When the server socket accepts a client connection request, it forms a new socket to connect to the client, so that the listening connection can remain open to accept other client requests

Server connections

Server connections are formed by server sockets when a listening socket accepts a client request A description of the server socket that completes the connection to the client is sent to the client when the server accepts the connection The connection is established when the client socket receives this description and completes the connection

Trang 13

Describing sockets

Sockets let your network application communicate with other systems over the network Each socket can be viewed as an endpoint in a network connection It has an address that specifies:

• The system on which it is running

• The types of interfaces it understands

• The port it is using for the connection

A full description of a socket connection includes the addresses of the sockets on both ends of the connection You can describe the address of each socket endpoint by supplying both the IP address or host and the port number

Before you can make a socket connection, you must fully describe the sockets that form its endpoints Some of the information is available from the system your application is running on For instance, you do not need to describe the local IP address of a client socket—this information is available from the operating system.The information you must provide depends on the type of socket you are working with Client sockets must describe the server they want to connect to Listening server sockets must describe the port that represents the service they provide

Describing the host

The host is the system that is running the application that contains the socket You can describe the host for a socket by giving its IP address, which is a string of four numeric (byte) values in the standard Internet dot notation, such as

123.197.1.2

A single system may support more than one IP address

IP addresses are often difficult to remember and easy to mistype An alternative is to use the host name Host names are aliases for the IP address that you often see in Uniform Resource Locators (URLs) They are strings containing a domain name and service, such as

http://www.ASite.com

Most Intranets provide host names for the IP addresses of systems on the Internet You can learn the host name associated with any IP address (if one already exists) by executing the following command from a command prompt:

nslookup IPADDRESS

where IPADDRESS is the IP address you’re interested in If your local IP address

doesn’t have a host name and you decide you want one, contact your network administrator It is common for computers to refer to themselves with the name

localhost and the IP number 127.0.0.1.

Trang 14

Server sockets do not need to specify a host The local IP address can be read from the system If the local system supports more than one IP address, server sockets will listen for client requests on all IP addresses simultaneously When a server socket accepts a connection, the client socket provides the remote IP address.

Client sockets must specify the remote host by providing either its host name or IP address

Choosing between a host name and an IP address

Most applications use the host name to specify a system Host names are easier to remember, and easier to check for typographical errors Further, servers can change the system or IP address that is associated with a particular host name Using a host name allows the client socket to find the abstract site represented by the host name, even when it has moved to a new IP address

If the host name is unknown, the client socket must specify the server system using its IP address Specifying the server system by giving the IP address is faster When you provide the host name, the socket must search for the IP address associated with the host name, before it can locate the server system

Using ports

While the IP address provides enough information to find the system on the other end of a socket connection, you also need a port number on that system Without port numbers, a system could only form a single connection at a time Port numbers are unique identifiers that enable a single system to host multiple connections

simultaneously, by giving each connection a separate port number

Earlier, we described port numbers as numeric codes for the services implemented

by network applications This is actually just a convention that allows listening server connections to make themselves available on a fixed port number so that they can be found by client sockets Server sockets listen on the port number associated with the service they provide When they accept a connection to a client socket, they create a separate socket connection that uses a different, arbitrary, port number This way, the listening connection can continue to listen on the port number associated with the service

Client sockets use an arbitrary local port number, as there is no need for them to be found by other sockets They specify the port number of the server socket to which they want to connect so that they can find the server application Often, this port number is specified indirectly, by naming the desired service

Trang 15

Using socket components

The Internet palette page includes three socket components that allow your network application to form connections to other machines, and that allow you to read and write information over that connection These are:

to be concerned with the details of establishing the connection or managing the socket messages

If you want to customize the details of the connections that the socket components make on your behalf, you can use the properties, events, and methods of the socket objects

Getting information about the connection

After completing the connection to a client or server socket, you can use the client or server socket object associated with your socket component to obtain information

about the connection Use the LocalHost and LocalPort properties to determine the

address and port number used by the local client or server socket, or use the

RemoteHost and RemotePort properties to determine the address and port number

used by the remote client or server socket Use the GetSocketAddr method to build a

valid socket address based on the host name and port number You can use the

LookupPort method to look up the port number Use the LookupProtocol method to

look up the protocol number Use the LookupHostName method to look up the host

name based on the host machine’s IP address

To view network traffic in and out of the socket, use the BytesSent and BytesReceived

properties

Using client sockets

Add a TcpClient or UdpSocket component to your form or data module to turn your

application into a TCP/IP or UDP client Client sockets allow you to specify the server socket you want to connect to, and the service you want that server to provide Once you have described the desired connection, you can use the client socket component to complete the connection to the server

Each client socket component uses a single client socket object to represent the client endpoint in a connection

Trang 16

Specifying the desired server

Client socket components have a number of properties that allow you to specify the

server system and port to which you want to connect Use the RemoteHost property to

specify the remote host server by either its host name or IP address

In addition to the server system, you must specify the port on the server system that

your client socket will connect to You can use the RemotePort property to specify the

server port number directly or indirectly by naming the target service

Forming the connection

Once you have set the properties of your client socket component to describe the server you want to connect to, you can form the connection at runtime by calling the

Open method If you want your application to form the connection automatically

when it starts up, set the Active property to True at design time, using the Object

Inspector

Getting information about the connection

After completing the connection to a server socket, you can use the client socket object associated with your client socket component to obtain information about the

connection Use the LocalHost and LocalPort properties to determine the address and

port number used by the client and server sockets to form the end points of the

connection You can use the Handle property to obtain a handle to the socket

connection to use when making socket calls

Closing the connection

When you have finished communicating with a server application over the socket

connection, you can shut down the connection by calling the Close method The

connection may also be closed from the server end If that is the case, you will receive

notification in an OnDisconnect event.

Using server sockets

Add a server socket component (TcpServer or UdpSocket) to your form or data module

to turn your application into an IP server Server sockets allow you to specify the service you are providing or the port you want to use to listen for client requests You can use the server socket component to listen for and accept client connection requests

Each server socket component uses a single server socket object to represent the server endpoint in a listening connection It also uses a server client socket object for the server endpoint of each active connection to a client socket that the server accepts

Trang 17

Specifying the port

Before your server socket can listen to client requests, you must specify the port that

your server will listen on You can specify this port using the LocalPort property If

your server application is providing a standard service that is associated by

convention with a specific port number, you can also specify the service name using

the LocalPort property It is a good idea to use the service name instead of a port

number, because it is easy to introduce typographical errors when specifying the port number

Listening for client requests

Once you have set the port number of your server socket component, you can form a

listening connection at runtime by calling the Open method If you want your

application to form the listening connection automatically when it starts up, set the

Active property to True at design time, using the Object Inspector.

Connecting to clients

A listening server socket component automatically accepts client connection requests when they are received You receive notification every time this occurs in an

OnAccept event.

Closing server connections

When you want to shut down the listening connection, call the Close method or set the Active property to False This shuts down all open connections to client

applications, cancels any pending connections that have not been accepted, and then shuts down the listening connection so that your server socket component does not accept any new connections

When TCP clients shut down their individual connections to your server socket, you

are informed by an OnDisconnect event.

Responding to socket events

When writing applications that use sockets, you can write or read to the socket

anywhere in the program You can write to the socket using the SendBuf, SendStream,

or Sendln methods in your program after the socket has been opened You can read from the socket using the similarly-named methods ReceiveBuf and Receiveln The

OnSend and OnReceive events are triggered every time something is written or read

from the socket They can be used for filtering Every time you read or write, a read

or write event is triggered

Both client sockets and server sockets generate error events when they receive error messages from the connection

Socket components also receive two events in the course of opening and completing

a connection If your application needs to influence how the opening of the socket

Trang 18

Error events

Client and server sockets generate OnError events when they receive error messages from the connection You can write an OnError event handler to respond to these

error messages The event handler is passed information about

• What socket object received the error notification

• What the socket was trying to do when the error occurred

• The error code that was provided by the error message

You can respond to the error in the event handler, and change the error code to 0 to prevent the socket from raising an exception

Client events

When a client socket opens a connection, the following events occur:

• The socket is set up and initialized for event notification

• An OnCreateHandle event occurs after the server and server socket is created At this point, the socket object available through the Handle property can provide

information about the server or client socket that will form the other end of the connection This is the first chance to obtain the actual port used for the

connection, which may differ from the port of the listening sockets that accepted the connection

• The connection request is accepted by the server and completed by the client socket

• When the connection is established, the OnConnect notification event occurs.

Server events

Server socket components form two types of connections: listening connections and connections to client applications The server socket receives events during the formation of each of these connections

Events when listening

Just before the listening connection is formed, the OnListening event occurs You can use its Handle property to make changes to the socket before it is opened for listing

For example, if you want to restrict the IP addresses the server uses for listening, you

would do that in an OnListening event handler.

Trang 19

Events with client connections

When a server socket accepts a client connection request, the following events occur:

• An OnAccept event occurs, passing in the new TTcpClient object to the event handler This is the first point when you can use the properties of TTcpClient to

obtain information about the server endpoint of the connection to a client

• If BlockMode is bmThreadBlocking an OnGetThread event occurs If you want to provide your own customized descendant of TServerSocketThread, you can create one in an OnGetThread event handler, and that will be used instead of

TServerSocketThread If you want to perform any initialization of the thread, or

make any socket API calls before the thread starts reading or writing over the

connection, you should use the OnGetThread event handler for these tasks as well

• The client completes the connection and an OnAccept event occurs With a

non-blocking server, you may want to start reading or writing over the socket

connection at this point

Reading and writing over socket connections

The reason you form socket connections to other machines is so that you can read or write information over those connections What information you read or write, or when you read it or write it, depends on the service associated with the socket connection

Reading and writing over sockets can occur asynchronously, so that it does not block the execution of other code in your network application This is called a non-blocking connection You can also form blocking connections, where your application waits for the reading or writing to be completed before executing the next line of code

Trang 20

Reading and writing events

Non-blocking sockets generate reading and writing events when they need to read or

write over the connection You can respond to these notifications in an OnReceive or

OnSend event handler

The socket object associated with the socket connection is provided as a parameter to the read or write event handlers This socket object provides a number of methods to allow you to read or write over the connection

To read from the socket connection, use the ReceiveBuf or Receiveln method To write

to the socket connection, use the SendBuf, SendStream, or Sendln method.

Blocking connections

When the connection is blocking, your socket must initiate reading or writing over the connection It cannot wait passively for a notification from the socket connection Use a blocking socket when your end of the connection is in charge of when reading and writing takes place

For client or server sockets, set the BlockMode property to bmBlocking to form a

blocking connection Depending on what else your client application does, you may want to create a new execution thread for reading or writing, so that your application can continue executing code on other threads while it waits for the reading or writing over the connection to be completed

For server sockets, set the BlockMode property to bmBlocking or bmThreadBlocking to

form a blocking connection Because blocking connections hold up the execution of all other code while the socket waits for information to be written or read over the connection, server socket components always spawn a new execution thread for

every client connection when the BlockMode is bmThreadBlocking When the BlockMode

is bmBlocking, program execution is blocked until a new connection is established.

Trang 22

P a r t

IV

The chapters in “Developing COM-based applications” present concepts necessary for building COM-based applications, including Automation controllers,

Automation servers, ActiveX controls, and COM+ applications

Trang 24

C h a p t e r

40

Delphi provides wizards and classes to make it easy to implement applications based

on the Component Object Model (COM) from Microsoft With these wizards, you can create COM-based classes and components to use within applications or you can create fully functional COM clients or servers that implement COM objects,

Automation servers (including Active Server Objects), ActiveX controls, or

ActiveForms

Note COM components such as those on the ActiveX, COM+, and Servers tabs of the Component palette are not available for use in CLX applications This technology is for use on Windows only and is not cross-platform

COM is a language-independent software component model that enables interaction between software components and applications running on a Windows platform The key aspect of COM is that it enables communication between components, between applications, and between clients and servers through clearly defined interfaces Interfaces provide a way for clients to ask a COM component which features it supports at runtime To provide additional features for your component, you simply add an additional interface for those features

Applications can access the interfaces of COM components that exist on the same computer as the application or that exist on another computer on the network using a mechanism called Distributed COM (DCOM) For more information on clients, servers, and interfaces see, “Parts of a COM application,” on page 40-3

This chapter provides a conceptual overview of the underlying technology on which Automation and ActiveX controls are built Later chapters provide details on creating Automation objects and ActiveX controls in Delphi

Trang 25

COM as a specification and implementation

COM is both a specification and an implementation The COM specification defines how objects are created and how they communicate with each other According to this specification, COM objects can be written in different languages, run in different process spaces and on different platforms As long as the objects adhere to the written specification, they can communicate This allows you to integrate legacy code

as a component with new components implemented in object-oriented languages The COM implementation is built into the Win32 subsystem, which provides a number of core services that support the written specification The COM library contains a set of standard interfaces that define the core functionality of a COM object, and a small set of API functions designed for the purpose of creating and managing COM objects

When you use Delphi wizards and VCL objects in your application, you are using Delphi’s implementation of the COM specification In addition, Delphi provides some wrappers for COM services for those features that it does not implement directly (such as Active Documents) You can find these wrappers defined in the ComObj unit and the API definitions in the AxCtrls unit

Note Delphi’s interfaces and language follow the COM specification Delphi implements objects conforming to the COM spec using a set of classes called the Delphi ActiveX framework (DAX) These classes are found in the AxCtrls, OleCtrls, and OleServer units In addition, the Delphi interface to the COM API is in ActiveX.pas and

ComSvcs.pas

COM extensions

As COM has evolved, it has been extended beyond the basic COM services COM serves as the basis for other technologies such as Automation, ActiveX controls, Active Documents, and Active Directories For details on COM extensions, see

“COM extensions” on page 40-10

In addition, when working in a large, distributed environment, you can create transactional COM objects Prior to Windows 2000, these objects were not

architecturally part of COM, but rather ran in the Microsoft Transaction Server (MTS) environment With the advent of Windows 2000, this support is integrated into COM+ Transactional objects are described in detail in Chapter 46, “Creating MTS or COM+ objects.”

Delphi provides wizards to easily implement applications that incorporate the above technologies in the Delphi environment For details, see “Implementing COM objects with wizards” on page 40-19

Trang 26

Parts of a COM application

When implementing a COM application, you supply the following:

COM interfaces

COM clients communicate with objects through COM interfaces Interfaces are groups of logically or semantically related routines which provide communication between a provider of a service (server object) and its clients The standard way to depict a COM interface is shown in Figure 40.1:

Figure 40.1 A COM interface

For example, every COM object must implement the basic interface, IUnknown Through a routine called QueryInterface in IUnknown, clients can request other

interfaces implemented by the server

Objects can have multiple interfaces, where each interface implements a feature An interface provides a way to convey to the client what service it provides, without providing implementation details of how or where the object provides this service

COM interface The way in which an object exposes its services externally to clients

A COM object provides an interface for each set of related methods and properties Note that COM properties are not identical to properties on VCL objects COM properties always use read and write access methods

COM server A module, either an EXE, DLL, or OCX, that contains the code for a

COM object Object implementations reside in servers A COM object implements one or more interfaces

COM client The code that calls the interfaces to get the requested services from

the server Clients know what they want to get from the server (through the interface); clients do not know the internals of how the server provides the services Delphi eases the process in creating a client by letting you install COM servers (such as a Word document

or PowerPoint slide) as components on the Component Palette This allows you to connect to the server and hook its events through the Object Inspector

COM Object Interface

Trang 27

Key aspects of COM interfaces are as follows:

• Once published, interfaces are immutable; that is, they do not change You can rely

on an interface to provide a specific set of functions Additional functionality is provided by additional interfaces

• By convention, COM interface identifiers begin with a capital I and a symbolic

name that defines the interface, such as IMalloc or IPersist

• Interfaces are guaranteed to have a unique identification, called a Globally

Unique Identifier (GUID), which is a 128-bit randomly generated number

Interface GUIDs are called Interface Identifiers (IIDs) This eliminates naming

conflicts between different versions of a product or different products

• Interfaces are language independent You can use any language to implement a COM interface as long as the language supports a structure of pointers, and can call a function through a pointer either explicitly or implicitly

• Interfaces are not objects themselves; they provide a way to access an object Therefore, clients do not access data directly; clients access data through an interface pointer Windows 2000 adds an additional layer of indirection known as

an interceptor through which it provides COM+ features such as just-in-time activation and object pooling

• Interfaces are always inherited from the fundamental interface, IUnknown.

• Interfaces can be redirected by COM through proxies to enable interface method calls to call between threads, processes, and networked machines, all without the client or server objects ever being aware of the redirection For more information see , “In-process, out-of-process, and remote servers,” on page 40-7

The fundamental COM interface, IUnknown

All COM objects must support the fundamental interface, called IUnknown, a typedef

to the base interface type IInterface IUnknown contains the following routines:

Clients obtain pointers to other interfaces through the IUnknown method,

QueryInterface QueryInterface knows about every interface in the server object and

can give a client a pointer to the requested interface When receiving a pointer to an interface, the client is assured that it can call any method of the interface

Objects track their own lifetime through the IUnknown methods, AddRef and Release,

which are simple reference counting methods As long as an object’s reference count

is nonzero, the object remains in memory Once the reference count reaches zero, the interface implementation can safely dispose of the underlying object(s)

QueryInterface Provides pointers to other interfaces that the object supports.AddRef and Release Simple reference counting methods that keep track of the

object’s lifetime so that an object can delete itself when the client no longer needs its service

Trang 28

COM interface pointers

An interface pointer is a pointer to an object instance that points, in turn, to the implementation of each method in the interface The implementation is accessed

through an array of pointers to these methods, which is called a vtable Vtables are

similar to the mechanism used to support virtual functions in Delphi Because of this similarity, the compiler can resolve calls to methods on the interface the same way it resolves calls to methods on Delphi classes

The vtable is shared among all instances of an object class, so for each object instance, the object code allocates a second structure that contains its private data The client’s

interface pointer, then, is a pointer to the pointer to the vtable, as shown in the

following diagram

Figure 40.2 Interface vtable

In Windows 2000 and subsequent versions of Windows, when an object is running under COM+, an added level of indirection is provided between the interface pointer and the vtable pointer The interface pointer available to the client points at an interceptor, which in turn points at the vtable This allows COM+ to provide such services as just-in-time activation, whereby the server can be deactivated and reactivated dynamically in a way that is opaque to the client To achieve this, COM+ guarantees that the interceptor behaves as if it were an ordinary vtable pointer

COM servers

A COM server is an application or a library that provides services to a client

application or library A COM server consists of one or more COM objects, where a COM object is a set of properties and methods

Clients do not know how a COM object performs its service; the object’s

implementation remains encapsulated An object makes its services available

through its interfaces as described previously.

In addition, clients do not need to know where a COM object resides COM provides

transparent access regardless of the object’s location

Pointer to Function 1

Implementation

of interface functions

vtable pointer interface pointer

object

Pointer to Function 2 Pointer to Function 3

Trang 29

When a client requests a service from a COM object, the client passes a class identifier (CLSID) to COM A CLSID is simply a GUID that identifies a COM object COM uses this CLSID, which is registered in the system registry, to locate the appropriate server implementation Once the server is located, COM brings the code into memory, and has the server instantiate an object instance for the client This process is handled indirectly, through a special object called a class factory (based on interfaces) that creates instances of objects on demand

As a minimum, a COM server must perform the following:

• Register entries in the system registry that associate the server module with the class identifier (CLSID)

• Implement a class factory object, which manufactures another object of a

particular CLSID

• Expose the class factory to COM

• Provide an unloading mechanism through which a server that is not servicing clients can be removed from memory

Note Delphi wizards automate the creation of COM objects and servers as described in

“Implementing COM objects with wizards” on page 40-19

CoClasses and class factories

A COM object is an instance of a CoClass, which is a class that implements one or

more COM interfaces The COM object provides the services as defined by its interfaces

CoClasses are instantiated by a special type of object called a class factory Whenever

an object’s services are requested by a client, a class factory creates an object instance for that particular client Typically, if another client requests the object’s services, the class factory creates another object instance to service the second client (Clients can also bind to running COM objects that register themselves to support it.)

A CoClass must have a class factory and a class identifier (CLSID) so that it can be instantiated externally, that is, from another module Using these unique identifiers for CoClasses means that they can be updated whenever new interfaces are

implemented in their class A new interface can modify or add methods without affecting older versions, which is a common problem when using DLLs

Delphi wizards take care of assigning class identifiers and of implementing and instantiating class factories

Trang 30

In-process, out-of-process, and remote servers

With COM, a client does not need to know where an object resides, it simply makes a call to an object’s interface COM performs the necessary steps to make the call These steps differ depending on whether the object resides in the same process as the client,

in a different process on the client machine, or in a different machine across the network The different types of servers are known as:

As shown in Figure 40.3, for in-process servers, pointers to the object interfaces are in the same process space as the client, so COM makes direct calls into the object implementation

Figure 40.3 In-process server

Note This is not always true under COM+ When a client makes a call to an object in a different context, COM+ intercepts the call so that it behaves like a call to an out-of-process server (see below), even if the server is in-process See Chapter 46, “Creating MTS or COM+ objects” for more information working with COM+

In-process server A library (DLL) running in the same process space as the client,

for example, an ActiveX control embedded in a Web page viewed under Internet Explorer or Netscape Here, the ActiveX control is downloaded to the client machine and invoked within the same process as the Web browser.The client communicates with the in-process server using direct calls to the COM interface

Out-of-process server

(or local server)

Another application (EXE) running in a different process space but on the same machine as the client For example, an Excel

spreadsheet embedded in a Word document are two separate applications running on the same machine

The local server uses COM to communicate with the client Remote server A DLL or another application running on a different machine

from that of the client For example, a Delphi database application is connected to an application server on another machine in the network

The remote server uses distributed COM (DCOM) to access interfaces and communicate with the application server

Client Process

Client

Server In-process Object

Trang 31

As shown in Figure 40.4, when the process is either in a different process or in a different machine altogether, COM uses a proxy to initiate remote procedure calls

The proxy resides in the same process as the client, so from the client’s perspective,

all interface calls look alike The proxy intercepts the client’s call and forwards it to where the real object is running The mechanism that enables the client to access objects in a different process space, or even different machine, as if they were in their

own process, is called marshaling

Figure 40.4 Out-of-process and remote servers

The difference between out-of-process and remote servers is the type of interprocess communication used The proxy uses COM to communicate with an out-of-process server, it uses distributed COM (DCOM) to communicate with a remote machine DCOM transparently transfers a local object request to the remote object running on

a different machine

Note For remote procedure calls, DCOM uses the RPC protocol provided by Open Group’s Distributed Computing Environment (DCE) For distributed security, DCOM uses the NT LAN Manager (NTLM) security protocol For directory services, DCOM uses the Domain Name System (DNS)

The marshaling mechanism

Marshaling is the mechanism that allows a client to make interface function calls to remote objects in another process or on a different machine Marshaling

• Takes an interface pointer in the server’s process and makes a proxy pointer available to code in the client process

• Transfers the arguments of an interface call as passed from the client and places the arguments into the remote object’s process space

DCOM RPC

Client Process

Client

In-process Proxy

Out-of-Process Server

Object

Remote machine Remote machine

DCOM

Stub

Remote server

In-process Object COM

RPC

Trang 32

For any interface call, the client pushes arguments onto a stack and makes a function call through the interface pointer If the call to the object is not in-process, the call gets passed to the proxy The proxy packs the arguments into a marshaling packet and transmits the structure to the remote object The object’s stub unpacks the packet, pushes the arguments onto the stack, and calls the object’s implementation In essence, the object recreates the client’s call in its own address space.

The type of marshaling that occurs depends on what interface the COM object implements Objects can use a standard marshaling mechanism provided by the

IDispatch interface This is a generic marshaling mechanism that enables

communication through a system-standard remote procedure call (RPC) For details

on the IDispatch interface, see “Automation interfaces” on page 43-13 Even if the object does not implement IDispatch, if it limits itself to automation-compatible types

and has a registered type library, COM automatically provides marshaling support.Applications that do not limit themselves to automation-compatible types or register

a type library must provide their own marshaling Marshaling is provided either

through an implementation of the IMarshal interface, or by using a separately

generated proxy/stub DLL Delphi does not support the automatic generation of proxy/stub DLLs

Aggregation

Sometimes, a server object makes use of another COM object to perform some of its functions For example, an inventory management object might make use of a separate invoicing object to handle customer invoices If the inventory management object wants to present the invoice interface to clients, however, there is a problem:

Although a client that has the inventory interface can call QueryInterface to obtain the

invoice interface, when the invoice object was created it did not know about the inventory management object and can’t return an inventory interface in response to a

call to QueryInterface A client that has the invoice interface can’t get back to the

inventory interface

To avoid this problem, some COM objects support aggregation When the inventory

management object creates an instance of the invoice object, it passes it a copy of its

own IUnknown interface The invoice object can then use that IUnknown interface to handle any QueryInterface calls that request an interface, such as the inventory

interface, that it does not support When this happens, the two objects together are called an aggregate The invoice object is called the inner, or contained object of the aggregate, and the inventory object is called the outer object

Note In order to act as the outer object of an aggregate, a COM object must create the inner

object using the Windows API CoCreateInstance or CoCreateInstanceEx, passing its

IUnknown pointer as a parameter that the inner object can use for QueryInterface calls

In order to create an object that can act as the inner object of an aggregate, it must

descend from TContainedObject When the object is created, the IUnknown interface of

the outer object is passed to the constructor so that it can be used by the

QueryInterface method on calls that the inner object can’t handle.

Trang 33

COM clients

Clients can always query the interfaces of a COM object to determine what it is capable of providing All COM objects allow clients to request known interfaces In

addition, if the server supports the IDispatch interface, clients can query the server for

information about what methods the interface supports Server objects have no expectations about the client using its objects Similarly, clients don’t need to know how (or even where) an object provides the services; they simply rely on server objects to provide the services they advertise through their interfaces

There are two types of COM clients, controllers and containers Controllers launch the server and interact with it through its interface They request services from the COM object or drive it as a separate process Containers host visual controls or objects that appear in the container’s user interface They use predefined interfaces to negotiate display issues with server objects It is impossible to have a container relationship over DCOM; for example, visual controls that appear in the container's user interface must be located locally This is because the controls are expected to paint themselves, which requires that they have access to local GDI resources.Delphi makes it easier for you to develop COM clients by letting you import a type library or ActiveX control into a component wrapper so that server objects look like other VCL components For details on this process, see Chapter 42, “Creating COM clients.”

COM extensions

COM was originally designed to provide core communication functionality and to enable the broadening of this functionality through extensions COM itself has extended its core functionality by defining specialized sets of interfaces for specific purposes

The following lists some of the services COM extensions currently provide

Subsequent sections describe these services in greater detail

Automation servers Automation refers to the ability of an application to control

the objects in another application programmatically

Automation servers are the objects that can be controlled by other executables at runtime

ActiveX controls ActiveX controls are specialized in-process servers, typically

intended for embedding in a client application The controls offer both design and runtime behaviors as well as events

Active Server Pages Active Server Pages are scripts that generate HTML pages

The scripting language includes constructs for creating and running Automation objects That is, the Active Server Page acts as an Automation controller

Trang 34

The following diagram illustrates the relationship of the COM extensions and how they are built upon COM:

Figure 40.5 COM-based technologies

Active Documents Objects that support linking and embedding, drag-and-drop,

visual editing, and in-place activation Word documents and Excel spreadsheets are examples of Active Documents

Transactional objects Objects that include additional support for responding to

large numbers of clients This includes features such as in-time activation, transactions, resource pooling, and security services These features were originally handled by MTS but have been built into COM with the advent of COM+

just-Type libraries A collection of static data structures, often saved as a

resource, that provides detailed type information about an object and its interfaces Clients of Automation servers, ActiveX controls, and transactional objects expect type information to be available

Trang 35

COM objects can be visual or non-visual Some must run in the same process space as their clients; others can run in different processes or remote machines, as long as the objects provide marshaling support Table 40.1 summarizes the types of COM objects that you can create, whether they are visual, process spaces they can run in, how they provide marshaling, and whether they require a type library

Automation servers

Automation refers to the ability of an application to control the objects in another application programmatically, like a macro that can manipulate more than one application at the same time The server object being manipulated is called the Automation object, and the client of the Automation object is referred to as an Automation controller

Automation can be used on in-process, local, and remote servers

Automation is characterized by two key points:

• The Automation object defines a set of properties and commands, and describes their capabilities through type descriptions In order to do this, it must have a way

to provide information about its interfaces, the interface methods, and those methods’ arguments Typically, this information is available in a type library The Automation server can also generate type information dynamically when queried

via its IDispatch interface (see following).

• Automation objects make their methods accessible so that other applications can

use them For this, they implement the IDispatch interface Through this interface

an object can expose all of its methods and properties Through the primary method of this interface, the object’s methods can be invoked, once having been identified through type information

Table 40.1 COM object requirements

Object

Visual Object? Process space Communication Type library

Active Document Usually In-process, or

Automatically marshaled using

the IDispatch interface (for out-of

process and remote servers)

Required for automatic marshaling ActiveX Control Usually In-process Automatically marshaled using

the IDispatch interface

Required MTS or COM+ Occasionally In-process for MTS,

any for COM+

Automatically marshaled via a type library

Required In-process custom

interface object

Optionally In-process No marshaling required for

in-process servers

Recommended Other custom

interface object

Optionally In-process,

out-of-process, or remote

Automatically marshaled via a type library; otherwise, manually marshaled using custom interfaces

Recommended

Trang 36

Developers often use Automation to create and use non-visual OLE objects that run

in any process space because the Automation IDispatch interface automates the

marshaling process Automation does, however, restrict the types that you can use For a list of types that are valid for type libraries in general, and Automation

interfaces in particular, see “Valid types” on page 41-12

For information on writing an Automation server, see Chapter 43, “Creating simple COM servers.”

Active Server Pages

The Active Server Page (ASP) technology lets you write simple scripts, called Active Server Pages, that can be launched by clients via a Web server Unlike ActiveX controls, which run on the client, Active Server Pages run on the server, and return a resulting HTML page to clients

Active Server Pages are written in Jscript or VB script The script runs every time the server loads the Web page That script can then launch an embedded Automation server (or Enterprise Java Bean) For example, you can write an Automation server, such as one to create a bitmap or connect to a database, and this server accesses data that gets updated every time a client loads the Web page

Active Server Pages rely on the Microsoft Internet Information Server (IIS)

environment to serve your Web pages

Delphi wizards let you create an Active Server Object, which is an Automation object specifically designed to work with an Active Server Page For more information about creating and using these types of objects, see Chapter 44, “Creating an Active Server Page.”

ActiveX controls

ActiveX is a technology that allows COM components, especially controls, to be more compact and efficient This is especially necessary for controls that are intended for Intranet applications that need to be downloaded by a client before they are used ActiveX controls are visual controls that run only as in-process servers, and can be plugged into an ActiveX control container application They are not complete applications in themselves, but can be thought of as prefabricated OLE controls that are reusable in various applications ActiveX controls have a visible user interface, and rely on predefined interfaces to negotiate I/O and display issues with their host containers

ActiveX controls make use of Automation to expose their properties, methods, and events Features of ActiveX controls include the ability to fire events, bind to data sources, and support licensing

Trang 37

One use of ActiveX controls is on a Web site as interactive objects in a Web page As such, ActiveX is a standard that targets interactive content for the World Wide Web, including the use of ActiveX Documents used for viewing non-HTML documents through a Web browser For more information about ActiveX technology, see the Microsoft ActiveX Web site.

Delphi wizards allow you to easily create ActiveX controls For more information about creating and using these types of objects, see Chapter 45, “Creating an ActiveX control.”

Active Documents

Active Documents (previously referred to as OLE documents) are a set of COM services that support linking and embedding, drag-and-drop, and visual editing Active Documents can seamlessly incorporate data or objects of different formats, such as sound clips, spreadsheets, text, and bitmaps

Unlike ActiveX controls, Active Documents are not limited to in-process servers; they can be used in cross-process applications

Unlike Automation objects, which are almost never visual, Active Document objects can be visually active in another application Thus, Active Document objects are associated with two types of data: presentation data, used for visually displaying the object on a display or output device, and native data, used to edit an object

Active Document objects can be document containers or document servers While Delphi does not provide an automatic wizard for creating Active Documents, you

can use the VCL class, TOleContainer, to support linking and embedding of existing

Active Documents

You can also use TOleContainer as a basis for an Active Document container To

create objects for Active Document servers, use the COM object wizard and add the appropriate interfaces, depending on the services the object needs to support For more information about creating and using Active Document servers, see the Microsoft ActiveX Web site

Note While the specification for Active Documents has built-in support for marshaling in cross-process applications, Active Documents do not run on remote servers because they use types that are specific to a system on a given machine such as window handles, menu handles, and so on

Trang 38

Transactional objects

Delphi uses the term “transactional objects” to refer to objects that take advantage of the transaction services, security, and resource management supplied by Microsoft Transaction Server (MTS) (for versions of Windows prior to Windows 2000) or COM+ (for Windows 2000 and later) These objects are designed to work in a large, distributed environment

The transaction services provide robustness so that activities are always completed

or rolled back (the server never partially completes an activity) The security services allow you to expose different levels of support to different classes of clients The resource management allows an object to handle more clients by pooling resources or keeping objects active only when they are in use To enable the system to provide

these services, the object must implement the IObjectControl interface To access the services, transactional objects use an interface called IObjectContext, which is created

on their behalf by MTS or COM+

Under MTS, the server object must be built into a library (DLL), which is then installed in the MTS runtime environment That is, the server object is an in-process server that runs in the MTS runtime process space Under COM+, this restriction does not apply because all COM calls are routed through an interceptor To clients, the difference between MTS and COM+ is transparent

MTS or COM+ servers group transactional objects that run in the same process space Under MTS, this group is called an MTS package, while under COM+ it is called a COM+ application A single machine can be running several different MTS packages (or COM+ applications), where each one is running in a separate process space

To clients, the transactional object may appear like any other COM server object The client need never know about transactions, security, or just-in-time activation unless

it is initiating a transaction itself

Both MTS and COM+ provide a separate tool for administering transactional objects This tool lets you configure objects into packages or COM+ applications, view the packages or COM+ applications installed on a computer, view or change the

attributes of the included objects, monitor and manage transactions, make objects available to clients, and so on Under MTS, this tool is the MTS Explorer Under COM+ it is the COM+ Component Manager

Trang 39

Type libraries

Type libraries provide a way to get more type information about an object than can

be determined from an object’s interface The type information contained in type libraries provides needed information about objects and their interfaces, such as what interfaces exist on what objects (given the CLSID), what member functions exist

on each interface, and what arguments those functions require

You can obtain type information either by querying a running instance of an object or

by loading and reading type libraries With this information, you can implement a client which uses a desired object, knowing specifically what member functions you need, and what to pass those member functions

Clients of Automation servers, ActiveX controls, and transactional objects expect type information to be available All of Delphi’s wizards generate a type library automatically, although the COM object wizard makes this optional You can view or

edit this type information by using the Type Library Editor as described in

Chapter 41, “Working with type libraries.”

This section describes what a type library contains, how it is created, when it is used, and how it is accessed For developers wanting to share interfaces across languages, the section ends with suggestions on using type library tools

The content of type libraries

Type libraries contain type information, which indicates which interfaces exist in

which COM objects, and the types and numbers of arguments to the interface methods These descriptions include the unique identifiers for the CoClasses

(CLSIDs) and the interfaces (IIDs), so that they can be properly accessed, as well as the dispatch identifiers (dispIDs) for Automation interface methods and properties Type libraries can also contain the following information:

• Descriptions of custom type information associated with custom interfaces

• Routines that are exported by the Automation or ActiveX server, but that are not interface methods

• Information about enumeration, record (structures), unions, alias, and module data types

• References to type descriptions from other type libraries

Trang 40

Creating type libraries

With traditional development tools, you create type libraries by writing scripts in the Interface Definition Language (IDL) or the Object Description Language (ODL), then running that script through a compiler However, Delphi automatically generates a type library when you create a COM object (including ActiveX controls, Automation objects, remote data modules, and so on) using any of the wizards on the ActiveX or Multitier page of the new items dialog (You can opt not to create a type library when using the COM object wizard.) You can also create a type library by choosing from the main menu, File|New|Other, select the ActiveX tab, and choose Type Library You can view the type library using Delphi’s Type Library editor You can easily edit your type library using the Type Library editor and Delphi automatically updates the corresponding tlb file (binary type library file) when the type library is saved For any changes to Interfaces and CoClasses that were created using a wizard, the Type Library editor also updates your implementation files For more information on using the Type Library editor to write interfaces and CoClasses, see Chapter 41,

“Working with type libraries.”

When to use type libraries

It is important to create a type library for each set of objects that is exposed to external users, for example,

• ActiveX controls require a type library, which must be included as a resource in the DLL that contains the ActiveX controls

• Exposed objects that support vtable binding of custom interfaces must be

described in a type library because vtable references are bound at compile time Clients import information about the interfaces from the type library and use that information to compile For more information about vtable and compile time binding, see “Automation interfaces” on page 43-13

• Applications that implement Automation servers should provide a type library so that clients can early bind to it

• Objects instantiated from classes that support the IProvideClassInfo interface, such

as all descendants of the VCL TTypedComObject class, must have a type library.

• Type libraries are not required, but are useful for identifying the objects used with OLE drag-and-drop

When defining interfaces for internal use only (within an application) you do not need to create a type library

Ngày đăng: 12/08/2014, 09:21

TỪ KHÓA LIÊN QUAN