Creating Callback Enabled Clients for Asynchronous Web Services

(http://dev2dev.bea.com/pub/a/2005/03/callback_clients.html)

 

 

Published on dev2dev (http://dev2dev.bea.com/)
 http://dev2dev.bea.com/pub/a/2005/03/callback_clients.html
 See this if you're having trouble printing code examples

Creating Callback Enabled Clients for Asynchronous Web Services

by Reza Shafii
03/14/2005

Abstract

Web services are a promising technology that play an important role in Service Oriented Architectures (SOA). A key, emerging aspect of this technology is the ability to provide asynchronous services. Although today’s web service standards contain specifications for providing such asynchronous services, the details on using them from a client application perspective can be confusing and unclear. Web services callbacks are an important element in the realization of these asynchronous services. This article provides a practical guide to the creation of client applications for web services that contain callback operations. All code segments shown in this article are from the included example, which you can download. The example contains the complete implementation of these code segments and usage guidelines.

Terminology

Before starting a discussion on callback-enabled clients, it is important that we clarify the terminology involved. The following diagram shows the main entities involved when a client uses a Web service with a callback operation.

Figure 1
Figure 1. A client making a call to a web service

This figure depicts a client making a call to a web service. The web service can then respond, at some later time, by making a call back to the client. Therefore, a client of a web service that contains a callback operation is special in that the client itself must provide an endpoint. We call this the callback endpoint and define an endpoint as a unique address identified by a URI to which SOAP request messages can be sent.

The client itself starts the interaction with the web service by sending a SOAP message to the web service endpoint. The correlated request messages sent by the client to the web service and their associated response messages form the client initiated operations. As mentioned, the client can process the request messages sent by the web service to its own callback endpoint. Together, the correlated request and response messages are referred to as a callback operation.

With this terminology in mind, let's take a closer look at the concept of web service callbacks and their relationship to conversational web services and asynchronous web service invocation.

Asynchronous vs. Callbacks vs. Conversational

The concept of an asynchronous web service invocation is sometimes confused with the idea of web service callbacks and conversational web services. Although related, the three concepts are different.

An asynchronous web service invocation means that the client is able to send a SOAP message request without blocking to receive the corresponding response message from the server. The process of making such asynchronous web service calls on BEA WebLogic Platform 8.1 web services is already comprehensively documented and is therefore not discussed further in this article.

Web service callbacks refer to scenarios that involve the web service provider sending a SOAP message back to its clients. The Web Services Description Language (WSDL) specifications define such operations as being of the type “solicit/response.” Clients of web services that support callback operations must have a web service endpoint themselves, which the web service can use for sending callback requests at any point in time, or, in other words, asynchronously. Note that this is unrelated to the concept of asynchronous invocation discussed earlier.

A web service is conversational if the series of messages going back and forth between the two endpoints are tracked with a unique conversation ID with specific operations flagged to start and end the flow of messages. Web services that provide callbacks are also, by definition, conversational. This is because in order for the web service to be able to make a callback call on a client, it has to have its callback endpoint information. This is only possible after an initial invocation has been made by the client. Therefore, at the very least, the initial operation initiated by the client and the callback operation made by the web service are related to each other and must be tracked with a unique conversation ID. If this is not done, there is no way for the client to differentiate between callback operations relating to different initiating calls.

We will now take these considerations into account and create callback-enabled clients. As we've just seen, these clients form the basis of solicit-response and conversational web services.

Creating Callback-Enabled Clients

As discussed earlier, callback-enabled web service clients need to provide a callback endpoint capable of asynchronously receiving and processing callback operation messages. To avoid the complications of having to provide a callback endpoint, a technique known as polling can be used as an alternative. However, this technique requires the client to periodically call the server to check for callback events. The overhead of these calls can be significant if the event in question does not occur frequently. This overhead can be avoided by having the client provide a callback endpoint and process the callback operations directly.

It should also be noted that although it is possible to create callback-enabled clients by using a web service over JMS (if such binding is offered), this approach has some limitations, one of the important ones being that it forces the client to use the same JMS implementation as the web service provider. We will therefore concentrate on accomplishing our task over the HTTP transport. There are two areas that require attention in creating such a client: the creation of proper client-initiated SOAP messages, and the handling of callback operations.

When our client initiates operations of a web service containing a callback, it needs to somehow include the URI of the callback endpoint on which it is listening within the request message. The Web Services Addressing and the SOAP Conversation Protocol specifications both define a SOAP header element that allows you to achieve this goal. Ideally, the specification used in specifying the callback endpoint would not matter. However, most web services containers, including BEA WebLogic Server 8.1, do not yet contain an implementation of the Web Services Addressing specifications. Currently, BEA WebLogic Workshop 8.1 web services support the SOAP Conversation Protocol specifications and that is the example used within our example client.

According to the SOAP Conversation Protocol, the required SOAP headers differ depending on the phase of the conversation. For the first client-initiated (start) operation within the conversation, we need to provide the web service with our callback endpoint through the callbackLocation header element. All operations, including the first one, will also require a unique ID that will be used in our SOAP messages throughout the dialogue. This is achieved through the conversationID element. The following is an example of a SOAP request message that starts a callback-enabled conversation:

<soapenv:Envelope soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:env="http://schemas.xmlsoap.org/soap/envelop/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"> <soapenv:Header> <con:StartHeader soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next" soapenv:mustUnderstand="0" xmlns:con="http://www.openuri.org/2002/04/soap/conversation/"> <con:conversationID>[123456]:192.168.1.100:8181</con:conversationID> <con:callbackLocation> http://192.168.1.100:8181/StockNotificationCallback </con:callbackLocation> </con:StartHeader> </soapenv:Header> <soapenv:Body> <n1:registerForThresholdNotif xmlns:n1="http://www.openuri.org/"> <n1:stockTicker>CCC</n1:stockTicker> <n1:threshold>10</n1:threshold> </n1:registerForThresholdNotif> </soapenv:Body> </soapenv:Envelope>

Most of the existing Java web service toolkits (for example, BEA WebLogic’s clientgen, Apache Axis, and JWSDP) allow you to create a proxy library that can be used by client applications to easily invoke web services operations. However, none of these frameworks supports callback operations with the main issue being that their proxies do not generate the required headers. Until such support is provided, it would be highly desirable to be able to use all the benefits of these frameworks (for example, complex type XML mapping) by extending them with support for callback operations. One technique for achieving this result is the use of a SOAP message handler.

All the web services toolkits named above can support SOAP message handlers. A message handler is a Java class that implements the javax.xml.rpc.handler.GenericHandler interface and contains methods called right before sending out (or after receiving) a SOAP message. We can introduce a message handler within our client that is able to find out the current phase of a particular conversation and accordingly extend the outgoing request message with the required headers.

It is important to note that the client SOAP message handler must be able to determine the phase of the conversation that the message in question belongs to so that the appropriate header elements are created. The generation of the conversation ID is also a task that is left up to the client handler.

Once the extended request message is received by the web service endpoint, it will then send request messages to the callback endpoint specified by the callbackLocation element of the start message. In most cases, the client process itself needs to provide this endpoint and handle the callback messages appropriately. If our client is running within a web service container, this could be accomplished by deploying a web service with the callback operation within the same container. However, if the client is not running within a container, the job can be accomplished by implementing the callback endpoint within a lightweight container embedded in the client process itself. This gives us the ability to invoke the client generated operations and handle the incoming callback operations within the same process context. Note that the processing entity behind the callback endpoint (and within the client) needs to be able to handle the XML mapping of the message parameters as well as the dispatching of the operation to the right area of code.

Off course the client could also choose to specify a callback endpoint living within a container separate from the calling process by simply setting the callbackLocation header element appropriately.

As we have seen, the creation of clients for web services containing callback operations is not trivial and contains complex elements including the handling of SOAP messages, management of the conversation (both in terms of phases and IDs), mapping of parameters, and dispatching of operations. These complexities are all abstracted when the web service in question is accessed through a BEA WebLogic Workshop Service Control, which automatically performs all these operations for the user.

Creating Callback-Enabled Client Using a Service Control

The accessing of web services through a WebLogic Workshop Service Control is already well-documented. This solution is by far the simplest way to use callback-enabled web services if the client entity is able to use controls (that is, it is a Java Process Definition business process or another control; Page Flows are not able to use control callbacks). All the complexities involved in accessing callback-enabled web services are abstracted by this method.

Example Stock Notification Service

The example included in this article contains a Stock Notification conversational web service and a sample client illustrating the concepts discussed here. The web service provides operations allowing clients to register stock tickers and an associated threshold price. The service then monitors the stock, and every time the price passes that threshold, notifies the client through a callback (onThresholdPassed()).

Figure 2
Figure 2. This diagram illustrates the configuration for our example

It is clear that a polling technique is not an optimal solution for the creation of our client: Stock prices could pass their associated thresholds on a frequent basis or very seldom. A short polling interval could therefore lead to many unnecessary calls whereas a long polling interval could result in the client being notified of a threshold crossing long after the fact.

The implementation of a callback endpoint within the client application seems like a better choice. Let's first look at how the example client sends operations to the StockNotification web service. We have implemented the client using two distinct techniques. The first technique uses the WebLogic Workshop-generated proxy library and is implemented by the makeCallUsingBEAProxy() method of the StockNotificationClient class:

public void makeCallUsingBEAProxy() { try { // Get the proxy instance so that we can start calling the web service operations StockNotificationSoap sns = null; StockNotification_Impl snsi = new StockNotification_Impl(); sns = snsi.getStockNotificationSoap(); // Register our conversational handler so that it can properly set our // our conversation headers with a callback location QName portName = new QName("http://www.openuri.org/", "StockNotificationSoap"); HandlerRegistry registry = snsi.getHandlerRegistry(); List handlerList = new ArrayList(); handlerList.add(new HandlerInfo(ClientConversationHandler.class, null, null)); registry.setHandlerChain(portName, handlerList); // Register, call some methods, then sleep a bit so that our callback // location can receive some notifications and finally finish the conversation. sns.registerForThresholdNotif("AAAAA", "100"); sns.addToRegistration("BBBBB", "5"); StockList stocks = sns.getAllRegisteredStocks(); ... sns.endAllNotifications(); } catch (Exception e) { throw new RuntimeException(e); } }

As you can see in this code segment, we are able to use the classes generated by clientgen as we would normally. The only thing that stands out in this code as compared to the invocation of a web service without callbacks is the instantiation and registration of a client-side SOAP message handler at the beginning of the method. This handler intercepts the outgoing SOAP messages and adds the necessary conversational headers. Every time a SOAP request message is sent from the client process the handleRequest() method of our message handler is called with a MessageContext object containing information about the outgoing SOAP request. Below is a code segment of our example client’s message handler:

package weblogic.webservice.core.handler; ... public class ClientConversationHandler extends GenericHandler { public boolean handleRequest(MessageContext ctx) { ... if (phase.equals("START")) { headerElement = (SOAPHeaderElement) header .addChildElement("StartHeader", "con", "http://www.openuri.org/2002/04/soap/conversation/"); headerElement.addChildElement("con:callbackLocation") .addTextNode(CALLBACK_URI); } else if (phase.equals("CONTINUE") || phase.equals("FINISH")) { headerElement = (SOAPHeaderElement) header .addChildElement("ContinueHeader", "con", "http://www.openuri.org/2002/04/soap/conversation/"); } headerElement.addChildElement("con:conversationID").addTextNode(convID); ... } }

The proxy library generated by the BEA clientgen tool already uses a default client-side SOAP message handler that creates the conversational StartHeader header element. Unfortunately, currently clientgen output does not support callback operations and therefore the default handler does not create the required callbackLocation sub-element. We therefore have to ensure that our own message handler overrides the default conversational handler so as to manage the extra task of creating the callbackLocation header. We do this by ensuring that our handler is created within the same package as the default handler, namely weblogic.webservice.core.handler, and that it has the exact same class name as ClientConversationHandler. Note that this technique involves overriding the existing conversation message handler and therefore is not guaranteed to be forward-compatible. This example, however, does show how a message handler could be used for the creation of the callback headers and this concept can be used with any other web services framework supporting SOAP message handlers.

An alternative to the technique of using SOAP message handlers along with proxy classes is to use the JAXM API to directly create the SOAP request messages and send them to the web service. This is the second technique used by our example client and is implemented within the makeCallsUsingJAXM() and callMethodFromFile() methods of the StockNotificationClient class:

public void makeCallsUsingJAXM() { callMethodFromFile("C:\\registerForNotifSOAP.xml"); ... callMethodFromFile("C:\\endAllNotifSOAP.xml"); } private void callMethodFromFile(String fileName) { try { // Create a SOAP connection object SOAPConnectionFactory scf = SOAPConnectionFactory.newInstance(); SOAPConnection conn = scf.createConnection(); // Create the SOAP request message from the specified file MessageFactory mf = MessageFactory.newInstance(); SOAPMessage msg = mf.createMessage(); SOAPPart sp = msg.getSOAPPart(); // Read the file content into a string and replace the conversation ID with // the current one. String fileContent = readFileIntoString(fileName); fileContent = fileContent.replaceFirst(CONV_ID_HOLDER, ConvIDGenerator.getInstance(). getConversationID()); StreamSource prepMsg = new StreamSource(new StringBufferInputStream( fileContent)); sp.setContent(prepMsg); msg.saveChanges(); // Make the actual call conn.call(msg, TARGET_SERVICE_URI); conn.close(); } catch (Exception ex) { throw new RuntimeException(ex); } }

The callMethodFromFile() method reads the SOAP message from the specified file, replaces the message’s conversation ID with the client’s current conversation ID, and finally makes the actual call. When using the JAXM approach, the Java to XML mapping of operation parameters and return values must be implemented by the client. We have avoided this task by using pre-generated SOAP messages (that already contain the required parameter values) from the file. Although this approach serves as a good conceptual illustration, it is most likely not a feasible solution for clients containing a reasonable level of complexity. Such clients must create the messages programmatically from scratch using JAXM along with a Java to XML mapping API.

Now that we have reviewed the areas of our client responsible for creating the web service operations, let's turn to the implementation of the client’s callback endpoint and the processing of the callback messages coming from the web service. Since our callback endpoint needs to be able to handle the incoming HTTP requests, a servlet could be a logical choice. Further, it would be highly desirable to have a servlet that is able to extract the SOAP messages included within the incoming HTTP requests and provide it to us in an easy-to-use form. The ReqRespListener interface and the JAXMServlet class of the javax.xml.messaging package provide us with this functionality. Once properly deployed, servlets that use this interface and class will have all targeted HTTP post requests automatically converted to SOAPMessage instances passed to us through the onMessage() method. The following code shows the onMessage() method implementation for our example client.

public class CallBackHandlerServlet extends JAXMServlet implements ReqRespListener { public SOAPMessage onMessage(SOAPMessage message) { try { // We have just received a SOAP message at the callback // endpoint. In this example we will just assume that // the message received is in fact the onThresholdPassed // callback request. However, a servlet handling // multiple callbacks cannot make this assumption and // should process the SOAP message to see what callback // it relates to and do as appropriate for each. String stockTicker = extractOnThresholdPassedArgument(message); System.out.println("[DEV2DEV CALLBACK EXAMPLE]: Received treshold notification for: " + stockTicker); // Now we have to create a proper response to the callback // request. Returning this response as part of the onMessage() // method will ensure that the SOAP response gets back to the server. SOAPMessage response = createThresholdPassedResponse(); return response; } catch (Exception e) { throw new RuntimeException(e); } } ... }

Once a callback request message is received by the onMessage() method, our client then extracts the stock ticker argument, prints it to the standard output, and creates the correlated response message that is returned to the web service by our servlet. Clients that use web services that contain more than a single callback operation will also need to dispatch the incoming request to an appropriate area of client code based on the corresponding callback operation.

Although our servlet contains the appropriate code for the processing of incoming onThresholdPassed() callback messages from the web services, it needs to be deployed within a servlet container listening on the callback URI to complete the implementation of the callback endpoint. The Jetty open source project contains a lightweight servlet container that can be embedded within our client. The deployment of the CallBackHandlerServlet servlet within an embedded Jetty container allows us to have the callback endpoint reside within the client Java process. The StockNotificationCallbackProcessor class is a utility class used by our client to start the Jetty server and deploy the CallBackHandlerServlet servlet:

public class StockNotificationCallbackProcessor { public static final String CALLBACK_SERVER_PORT = ":8181"; public static final String CALLBACK_SERVLET_CLASS = "asynchwsconsumer.CallBackHandlerServlet"; public static final String CALLBACK_SERVLET_NAME = "CallBackHandlerServlet"; private HttpServer server; public StockNotificationCallbackProcessor() {} public void startListening() { try { // Configure the server so that we listen on the callback URI server = new Server(); server.addListener(CALLBACK_SERVER_PORT); ServletHttpContext context = (ServletHttpContext) server.getContext("/"); context.addServlet(CALLBACK_SERVLET_NAME, "/*", CALLBACK_SERVLET_CLASS); // Start the http server server.start(); } catch (Exception e) { throw new RuntimeException(e); } } public void stopListening() { try { server.stop(); } catch (Exception e) { throw new RuntimeException(e); } } }

The startListening() method deploys the CallBackHandlerServlet on port 8181 and configures the embedded servlet container so that all HTTP requests are directed to this port. This method also starts the embedded servlet container.

Now that we have examined both the creation of the web service operations and the processing of the callback operations, let's see how the main() method of our example client uses these elements:

public static void main(String[] args) { StockNotificationClient snClient = new StockNotificationClient(); snClient.snCallbackProcessor.startListening(); snClient.makeCallUsingBEAProxy(); ConvIDGenerator.getInstance().resetConversationID(); snClient.makeCallsUsingJAXM(); snClient.snCallbackProcessor.stopListening(); }

As you can see, the method starts by setting up the callback endpoint (which, as we saw before, involves starting the embedded servlet container and deploying the callback processing servlet to it). The method then uses the BEA clientgen proxy to make calls on the stock notification web service. Given that this interaction with the web services completes the conversation by calling the endAllNotifications() end operation, the client needs to change the conversation ID to start a new conversation. Our client uses the ConvIDGenerator singleton class to manage conversation IDs, and that class uses the java.rmi.dgc.VMID class to create properly formatted unique conversation IDs.

Once the conversation ID has been changed, the client then uses JAXM to once again make calls on the stock notification web service. Finally, the client stops the embedded servlet container and the process ends.

We have now completed our analysis of the example client that can be downloaded as part of this article. When you run this client against the stock notification web services, both the client and the web service will display messages to the standard output describing the various phases of the conversation including the processing of the callback operations.

Conclusion

This article shows the steps involved in the creation of a stand-alone client process for web services containing callback operations. Such a client needs to manage the conversational aspects of the web service calls and provide an endpoint that can be used by the web service for callback operations.

Download

CallbackExample.zip (1.7Mb) - This file contains the complete example application described in this article.

References

Reza Shafii works for BEA Systems professional services.


Return to dev2dev.

 

Posted by '김용환'
,

 

Asynchronous operations and Web services, Part 1: A primer on asynchronous transactions

(http://www-128.ibm.com/developerworks/webservices/library/ws-asynch1.html)

 

Level: Introductory

Holt Adams (rhadams@us.ibm.com), Engagement Manager/Solutions Architect, IBM jStart

01 Apr 2002

Not all Web services work synchronously; in some situations, responses to Web service requests are not provided immediately, but rather sometime after the initial request transactions complete. Such asynchronous operations aren't explicitly supported by Web services specifications and standards; however, those standards do include the infrastructure and mechanisms on which asynchronous operations can be based. In this article, Holt Adams explains why any Web services architect needs to understand how asynchronous operations work. This article will help you begin to adapt your own services for an asynchronous environment.
Posted by '김용환'
,

Web services integration patterns for Java applications using open source frameworks, Part 1: Implementing invoke patterns

(http://www-128.ibm.com/developerworks/webservices/library/ws-pattern-open1.html)

 

05 May 2006

There are four primary patterns for integrating Web services. In this first of a two-part series, we suggest ways to develop a service and client to invoke Web services for all four service end-point patterns, using popular open source frameworks. We discuss two of the patterns, request-response and one-way end-point, covering both document-style and RPC Web services invocation styles. The next article in the series will describe the other two integration patterns, solicit-response and notification.
Posted by '김용환'
,

Really Simple Asynchronous Web Services

(http://www.computerworld.com/developmenttopics/development/story/0,10801,79698,00.html)

 

March 25, 2003 (Computerworld) -- The first word in SOAP (Simple Object Access Protocol) is "simple," but the world of Web services has become very complicated. In early 2000 the SOAP specification was published, and it was quickly followed by the SOAP with Attachments; Universal Description, Discovery and Interoperability (UDDI); and Web Services Description Language (WSDL) specifications. These core technologies have been very widely adopted, implemented and endorsed. Then came a plethora of proposals for additional functionality, positioned as extensions to the core technologies, such as WS-Security, WS-Transactions, WS-Routing, BPEL, WS-Coordination, HTTP-R and WS-Reliability.

It's not yet clear exactly what applications Web services are really going to be used for, and therefore it's not really clear whether or not all these additional specifications and technologies are really necessary. Most business applications have fundamental requirements around security and reliability that represent a kind of minimum criterion for adoption. Many, if not all, of the proposed extensions fall into these two major categories. But these basic requirements can actually be met using a very simple approach in which a lot of these complicated extensions aren't necessary.

Most current Web services applications are used in a connection-oriented manner. That is, in order to use the applications over the Internet, a connection is required between the service requester and service provider. But for the mobile traveler, and for the emerging world of wireless networks, always being connected may not be possible or practical.

In the world of high-speed, wireless networking and mobile Internet-enabled devices such as laptops, personal digital assistants (PDA), cellular telephones and automobiles, it is unlikely that a connection will always and constantly be available. A really simple solution works well in this environment, insulating users from worrying about connectivity loss. If a connection is present, the message is immediately transferred. If a connection is not present, the message is queued up for later transfer.

Connections also pose security risks because they represent a hole in the firewall. Many Web sites impose security checks through log-on popups and encrypted protocols to help prevent unwanted access to sensitive or valuable data, and to guard against intrusions. But this is a constant battle, and many viruses and other security breaches often occur despite the best precautions. A simple solution improves the situation through the use of file and directory protection, and by allowing an intermediary data store to be placed outside the firewall, thereby avoiding the need for direct connections.

The most popular transport protocol for Web services, HTTP, doesn't provide the type of message delivery guarantee business applications depend upon. A really simple alternative solution provides message delivery guarantees by using the file transfer protocol (FTP) to implement the type of reliable store-and-forward techniques found in message queuing middleware.

Figure 1 illustrates a simple solution to Web services connectivity, reliability and security issues by mapping SOAP messages to files and using FTP to transfer them over the Internet. By treating SOAP as files rather than on the wire streams, the file system can be used to implement a store-and-forward mechanism that improves reliability and allows applications to work equally well whether an Internet connection is present or not.

The solution is completely compatible with all Web services standards: WSDL can still be used to provide the SOAP message description, and headers can be added for any of the newly proposed specifications. The only difference is that the resulting SOAP message (which is by definition an XML file) is written to a file instead of to a network transport.

Figure 1, The Simple Solution Maps SOAP Messages to Files

File-based security protection can be added, including read- or write-only directories, access control and embedded digital signatures. Furthermore, an FTP directory server can be placed outside the firewall, or in the demilitarized zone (DMZ), eliminating the need to allow direct HTTP connections for Web services that access sensitive corporate documents and data.

Applications built using this approach can take advantage of richer client features for the end user, since the user is completely decoupled from the need to know whether or not a connection to the Internet is present at a given moment. Web services-based applications can take full advantage of features and functions in client-side technologies, such as Flash, Swing and Visual Basic graphical user interfaces (GUI), and interact with large files and graphic images more easily and with better performance.

Why Complexity Exists

The core specifications SOAP, WSDL and UDDI are widely adopted and implemented. They provide basic interoperability across widely disparate software domains and networks, and are sufficient for many applications. SOAP and WSDL are also defined to encompass the two major distributed computing communications paradigms: remote procedure call (RPC) and document or message-oriented interactions (the terms document and message are used synonymously in this article). But most developers are more familiar with the RPC-oriented interaction model of distributed computing, or prefer it, and the tendency to view Web services as RPCs creates most of the complications.

Figure 2 illustrates the difference between RPC-oriented and document-oriented Web services. RPC-oriented Web services implement the request/response communication paradigm, which is typically used for short-lived requests. Document-oriented Web services typically are used to implement longer-running interactions such as process flows. Technically, however, document-oriented interactions can be used for short-lived requests, and vice versa.

The request/response communication paradigm is a major feature of modern distributed computing environments, including CORBA, COM and Java 2 Enterprise Edition. Most new development of customized applications is carried out using one or more of these environments, and the RPC-oriented paradigm is easy to use and familiar to programmers. To a developer, an RPC is easy to use because it makes calls to remote programs and objects using the same basic language syntax used to perform local procedure and object calls.

Figure 2, Contrast Between RPC-Oriented and Document-Oriented Web Services

Document-oriented Web services, on the other hand, are much better matched to the store-and-forward communication paradigm common to message-oriented middleware systems such as MQSeries, Sonic MQ and MSMQ. Developers are not used to thinking of these systems as mechanisms for calling remote procedures and objects, although in practice they often are. Developers are also unused to dealing with data in the form of documents or messages (procedure or method arguments are the more typical form).

The majority of Web services tool kits, books, articles and products on the market today focus primarily on RPC-oriented Web services for these and other reasons. But the fact is that SOAP and WSDL are just not very well suited to RPC-style interactions.

RPC-oriented technology assumes the continual presence of a network connection, while message-oriented middleware works reliably whether the network connection is present or not. On the Internet today, connections are neither reliable nor guaranteed. And as the world moves more and more toward mobile connections, the reliability service guarantees are more likely to resemble a wireless telephone network than an office LAN.

RPC-oriented technology also typically depends upon a sharing state between the service requester and provider using a mechanism called a session or a conversation. Web services do not support this mechanism, meaning that typical add-on services to RPCs such as security, transactions and guaranteed delivery don't work as they do in existing RPC-oriented technologies and have to be reinvented for Web services. The misperception that Web services are well suited to RPC-oriented interactions leads to a lot of frustration, and a lot of effort in the Web services community to date has focused on filling the gaps between SOAP and "real" RPC-oriented technologies.

An equally valid approach, however, is to focus instead on the document-oriented, store-and-forward technologies for which Web services are much better suited. Instead of adding features and functionality to improve the fit for Web services as RPC-oriented technology, it is actually much easier and more productive to add features and functionality that improve the usage of Web services for message-oriented applications. SOAP messages, after all, are just XML documents, and are more simply transported as files than on the wire streams.

The Document-oriented Solution

Because Web services are better suited to the document-oriented style than that RPC-oriented style, it makes more sense to compare them to message-oriented middleware systems MQSeries, Sonic MQ and MSMQ. The document-oriented style of communications solves more of the barriers to adoption with the core standards than the RPC-oriented style does.

It's easy to think about entire SOAP messages as files, since they are fundamentally instances of XML documents, possibly with attachments. And therefore it's easy to think of using file transfer mechanisms as a very simple transport for SOAP messages. For this reason, most vendors have already implemented mappings of SOAP to message-oriented middleware such as the various Java Messaging Service (JMS) providers, MQSeries and MSMQ. However, these solutions are proprietary in the sense that they require the vendor's product in order to work.

A very simple, inexpensive and open mechanism for file transfer already exists, however, because every operating system has a file system, and the Internet has FTP, which altogether provides a worldwide, virtual file system for transporting SOAP messages.

All computers, whether laptops, desktops, specialized devices, mobile phones or PDAs, are capable of dealing with files. A very simple mechanism for transporting Web services requests, therefore, is to use ubiquitous file management capabilities to transport the messages from the source to the destination, and then execute the request once the destination is reached. Copying files is much simpler, more secure, and more reliable than dealing with a stream of bytes over the network.

From the point of view of the client application, or Web services requester, all that has to be done is write a file to a directory, something almost any application can do. A network connection is not required. Clients that can write XML files simplify things even more. Once a file is available in a local directory, intelligent Web services software can import the file, add a SOAP envelope and headers (if not already present), and transfer the XML file to a remote FTP site where it can be picked up by the service provider, parsed and executed. If everyone is connected and online, it happens immediately. If a connection is not available, it happens later, when a connection is available.

A Web services request can be forwarded to one or more additional intermediate directories, typically remote from the original client, before the request is ultimately executed. Responses typically flow back through the system following the reverse path: The response message is placed in a local reply directory and forwarded to the remote system for processing.

Treating SOAP messages as files and using a message-oriented architecture, reliability can be introduced at the transport level very easily. A file is not deleted from its source directory until it has successfully been transferred to its target directory, and so on.

File protection security can be added to the messages very easily. Directory protection can ensure that files are transferred in one direction only, target directories can be write-only, and source or input directories can be set up to be read-only. Furthermore, file transfer greatly reduces the need for logging on required by HTTP connections. A file protection password can be included in the file header, or in an FTP operation. Digital signature can easily be added to protect the contents of the XML file itself. A simple additional security precaution can be accomplished by placing the FTP server in a DMZ, or by using a trusted third party to host the FTP server completely outside the corporate firewall.

An Example of Product Architecture

An example of the simple architecture for handling asynchronous, document-oriented Web services interactions is described below.

Figure 3, Simple Asynchronous Web Services Architecture

In Figure 3, the left side of the dotted line illustrates the occasionally connected client components (that is, client applications that are tolerant of intermittent Internet connection), and the right side illustrates the server components (including Web services choreographies, content management systems and integrations with various back-end applications).

The client and server sides are connected through the gray box at the bottom labeled "Asynchronous SOAP Messaging (FTP, HTTP, JMS . . .)." The functionality represented by the gray box allows SOAP messages to be stored in files locally on the desktop if a connection is not available to the server side. In this architecture, the occasionally connected client can reliably send a Web service request to the server even though there may not be a connection available between the client and server when the Web service call is made.

In this scenario, the desktop application generates a service request to execute some service on the server side. The Intelligent Web Service Agent picks up the service request, which is responsible for generating a self-contained SOAP message and storing the message in a persistent store if no connection is available. When a connection is available later on, this SOAP message can be transferred immediately to the server side and executed.

The asynchronous SOAP message transport layer handles the transportation of this SOAP message reliably no matter whether the connection is available or not. The benefit of this architecture is that the client-side applications can continue to work whether they are connected to the Internet or not. Client-side applications therefore don't have to worry about being connected and can take advantage of rich local tools, easily work with large files and take part in long-running business process orchestrations.

Another benefit of this loosely coupled architecture is that the asynchronous SOAP messaging layer can be based on different transports, such as FTP, JMS and HTTP, and easily replaced depending on different application requirements. The architecture is kept as generic as possible so that the asynchronous transport layer can be easily replaced by different transports as required. The HTTP transport (or a specific synchronous transport such as Java Remote Method Invocation) can be used instead of the FTP transport, for example, if an application needs it.

In this loosely coupled approach, the interface between the desktop application and the client uses "incoming" and "outgoing" file folders. When a Web service request or document is dropped into the outgoing folder, the Intelligent Web Service Agent picks it up and does the necessary processing to generate a valid SOAP message with header information. The SOAP message is persisted to the persistent store by the agent in order to reliably make the Web service call later on when there is a connection available.

On the other side of the persistent store, the FTP transport agent, which is responsible for detecting the network connection, uploads the SOAP message to the FTP intermediate persistent store once a connection is available. Then the Web service message is downloaded from the FTP site to the server side by the server application and processed.

In the reverse case, the same FTP transport agent can download any SOAP response message from the FTP site whenever a connection is available and persist the server's response message to the local persistent store. The Intelligent Web Service Agent picks up the SOAP response from the persistent store, unwraps the SOAP response message and processes the content by placing the response message in the Incoming folder of the desktop client application.

Summary

File-based transfer mechanisms provide a really simple way to implement asynchronous Web services, resolving common concerns such as occasional connectivity, security and reliable messaging without adding the complexity of extended standards. File-based transfer mechanisms are consistent with current and emerging Web services standards.

Considerable frustration with current Web services technologies arises when comparing them with RPC-oriented middleware since by definition Web services are not well suited to the RPC-oriented interaction style. Web services are much better suited for the message-oriented interaction style. Extending Web services toward message-oriented middleware architectures provides a better way to improve short-term value than proposing complex RPC-oriented extensions.

Client-side applications benefit from the simple asynchronous architecture since they do not have to worry about whether or not they are connected to the Internet; and they can use better GUI tools, work with large documents and participate in long-running business process orchestrations.

Eric Newcomer is chief technology officer at IONA Technologies.

Posted by '김용환'
,

출처 :

http://kin.naver.com/db/detail.php?d1id=4&dir_id=412&eid=/okwD+W7iFpSGonrU5nWTJxYAB1KBk1v

 

 

우선 자본에 대해 말씀드리겠습니다.

자본이란 통상 기업의 운영에 소요되는자금을 기업내부 혹은 외부에서 조달한것과

과거 경영활동결과에 의해서 기업내부에 축적된 잉여금이라고 보시면 되며,

자본계정의 종류에는 1. 자본금  2. 자본잉여금, 3 이익잉여금, 4 자본조정계정이 있습니다.

 

1. 자본금

기업주와 주주등이 기업에 투자한 원금을 자본금이라고 합니다.

 

2. 자본잉여금(건설자본잉여금)

자본잉여금이란 주식의 발행,증자 또는 감자등과 같은 자본거래에 의하여 발생한 잉여금

으로 주식발행초과금, 감자차익 및 기타자본잉여금으로 구분됩니다.

ⓐ 주식발행초과금 

액면을 초과하여 주식을 발행할때 그 액면을 초과한 금액을 말하고 액면에 미달되어 주식을 발행한경우에는 주식할인발행차금이라고 부르며 "자본조정"과목으로 분류됩니다.

예)  발행가액 (a) - 액면가액 (b) = 주식발행초과금

        발행가액 (a) - 액면가액 (b) = 주식할인발행차금

ⓑ 감자차익

자본감소의 경우에 그 감소액의 주식의 소각,주금의 반환에 요한 금액과 결손의 보전에

충당한 금액을 초과한 때에 그 초과금액을 말합니다.

ⓒ 기타자본잉여금

자기주식처분이익으로서 자기주식처분손실을 차감한 금액과 그밖의 기타자본잉여금을

의미합니다.

 

3. 이익잉여금

영업활동의 결과로 이익이 발생한금액으로 보시면 되는데, 이런 이익잉여금을

이익준비금, 기타법정적립금, 임의적립금, 차기이월이익잉여금으로 구분하여 적립하거나

차기로 넘깁니다.

 

4. 자본조정

자본금, 자본잉여금이외의 임시적성격의 자본항목으로 자본과 부채의 양면적성격을

갖습니다.

ⓐ자본항목

미교부주식배당금, 투자유가증권평가이익, 해외사업환산대

ⓑ 부채항목

주식할인발행차금, 배당건설이자, 자기주식, 투자유가증권평가손실, 해외산업환산차

Posted by '김용환'
,

출처 :

http://kin.naver.com/db/detail.php?d1id=4&dir_id=402&eid=ZQrtLrfTGUp7eJ2l3TWgbtx4C0ZA/Jd+

 

주식회사가 배당이외의 방법으로 주주들에게 이익을 환원하는 방법으로는

여러가지 있을 수 있습니다.

현금배당, 주식배당 등과 같은 배당의 방법

유상으로 주주들로부터 주식을 사들여 소각하는 유상소각(유상감자)

무상증자의 방법으로 주식수를 증가시키는 것도 주주이익의 환원입니다.

또한, 이익소각이라고 있는데 이는 배당가능이익으로 주식을 사는것입니다.

 

유상소각과 이익소각은 비슷해보이지만

 이익소각의 방법은 자본금이 줄지않고 주식수만 줄어드는 것인데 반해

 유상소각의 경우 자본금이 줄어드는 감자의 방법입니다.

 

최근에 거래소 상장기업중에 동서산업이 유상소각을 계획하고 있습니다.

주주들로부터 시가로 주식을 매입한후 주식을 소각함으로써 주식수와 자본금을

동시에 줄이는 방법입니다.

 

이익소각은 한기평, 벽산건설등이 추진하여 종료된 것으로 알고 있습니다.

이들 회사는 발행주식수는 줄었지만 소각후 자본금은 그대로죠

Posted by '김용환'
,

감가상각을 계상하는 방법은 크게 두가지로 분류됩니다.

가속상각법은 시간이 지남에따라 더 많은 금액을 상각하는 것이고,

감속상각법은 점치 작은 금액을 상각해 나가는 것이지요.


다음과 같은 계산법으로 계산됩니다.


1. 정액법 : 매년 동일한 금액으로 감가상각액을 배분하는 방법입니다.

감가상각비 = (취득원가-잔존가액)/내용연수



* 용어는 다 아시죠? ^^; 그래두 짚고 넘어간다고 생각하고...

  취득원가는 유형자산을 샀을때의 금액,

  잔존가액은 나중에 유형자산을 처분할 때 받을 수 있는 금액정도로 해석하면 되구요

  내용연수는 유형자산을 사용할 기간(연도)를 말합니다.


2. 생산량비례법 : 특정목적을 달성하는데 공헌한 부분에 비례해서 감가상각합니다.

감가상각비 = {(취득원가-잔존가치)/내용연수기간 동안 총 생산량}X 회계연도 생산량


3. 정률법 : 유형자산의 수명을 생각하면 처음 샀을때 생산성이 더욱 뛰어나겠지요? 새거니까~ ^^; 시간이 지남에 따라 기계가 노화되서 생산량도 떨어 질겁니다. 그런것을 감안해서 초기에 감가상각비를 많이 계상하고 뒤로 갈수록 적게 계상하는 방법이지요.


매 연도 감가상각비 = 기초장부가액 X 정률(r)


*여기서 장부가액은 취득원가에서 지금까지 감가상각누계액을 차감한 잔액을 의미하지요.

정률은 수학적인 부분인데요..-_-;;

          n년후 장부가액 = 취득원가 X (1-r)ⁿ

                                   의 식으로 r의 값을 구해서 대입시켜야지요..^^;;

*아참... 정률법을 계산할때 중요한 부분은 잔존가치는 고려하지 않는다는 거죠~


4. 연수합계법 : 정률법과 마찬가지로 초기에 감가상각비를 많이 계상하고자 하는 방법입니다.

각 연도 감가상각비 = (취득원가-잔존가치) X 잔존내용연수/연수합계


* 잔존내용연수는 앞으로 기계를 사용할 연수를 말합니다. 만약 기계의 내용연수가 4라면 처음 기계를 사서 쓴해는 4, 다음해는 3, 그 다음해는 2... 이렇게 되겠죠.

* 연수합계는 4+3+2+1을 구하는 거죠. 내용연수가 만약 20년이라면 언제 계산하냐구요? 훗~ 수열에서 배웠었지요... n(n+1)/2 .... n 에 내용연수를 대입시켜서 계산합니다.



5. 이중체감잔액법 : 정률법과 아주 유산한 방법인데요, 앞에 정률법은 정률을 구하기가 복잡했지요^^; 그에 반에서 이중체감법은 쉬운 방법으로 정률을 계산해요.


                    이중체감잔액법의 정률 = 2 X  (1/내용연수)

                    매 연도 감가상각비 = 기초장부가액 X 정률

          * 이중체감잔액법 역시 계산할때 잔존가치를 고려하지 않아요..^^

 

 

Posted by '김용환'
,
WSDL 상세 2005-11-21 11:31
카테고리 : Apache Php Mysql http://blog.paran.com/sputnik/7025859

개요

WSDL은 문서 지향적 또는 프로시저 지향적인 정보를 포함한 메시지에서 작동하는 종점 집합으로서의 네트워크 서비스를 설명하는 XML 형식입니다. 이러한 작동 및 메시지에 대해 대략적으로 설명한 다음, 구체적인 네트워크 프로토콜 및 메시지 형식으로 연결하여 종점에 대해 정의합니다. 관련된 구체적인 종점은 추상 종점(서비스)과 결합되어 있습니다. WSDL은 통신에 사용되는 메시지 형식 또는 네트워크 프로토콜과는 상관 없이 종점 및 종점의 메시지를 설명하도록 확장할 수 있습니다. 하지만, 이 문서에 설명된 바인딩만이 SOAP 1.1, HTTP GET/POST 및 MIME과 함께 WSDL을 사용하는 방법을 설명합니다.

이 WSDL 언어 버전은 종점의 컴퍼지션 및 결합을 설명하는 프레임워크를 포함하지 않는 첫 번째 단계입니다. 계약을 설명하는 전체 프레임워크는 메시지를 받거나 보내는 순서 규칙과 같이 서비스의 동작을 표현하는 방법과 서비스를 작성하는 방법을 포함합니다. 서비스의 컴퍼지션은 모든 형식을 지원해야 하지만 런타임에 교환되고 바운드되는 서비스 참조와 함께 전달되는 참조를 허용해야 합니다. 특히, 후자는 런타임 계약 협상의 중요한 요소이며 참조 동작을 캡처하고 서비스를 중개합니다.

WSDL 스펙 작성자들은 (1)서비스를 작성하는 프레임워크 및 (2)서비스의 동작을 설명하는 프레임워크를 포함하는 WSDL의 수정된 버전 및/또는 추가 문서를 적시에 게시하고 있습니다.

맨 위로


상태

여기에서는 Ariba, IBM 및 Microsoft 내에서 서비스의 설명과 관련한 현재 고려 사항을 보여 주며 NASSL, SCL 및 SDL(이 분야에서의 이전 제안)의 개념을 통합합니다.

목차

1 소개
1.1 WSDL 문서 예제
1.2 국제 규칙
2 서비스 정의
2.1 WSDL 문서 구조
2.1.1 문서 명명 및 연결
2.1.2 제작 스타일
2.1.3 언어 확장성 및 바인딩
2.1.4 설명서
2.2 형식
2.3 메시지
2.3.1 메시지 부분
2.3.2 추상 메시지와 구체적인 메시지
2.4 포트 형식
2.4.1 단방향 작업
2.4.2 요청-응답 작업
2.4.3 검색-응답 작업
2.4.4 알림 작업
2.4.5 작업 내 요소의 이름
2.4.6 작업 내 매개 변수 순서
2.5 바인딩
2.6 포트
2.7 서비스
3 SOAP 바인딩
3.1 SOAP 예제
3.2 SOAP 바인딩이 WSDL을 확장하는 방법
3.3 soap:binding
3.4 soap:operation
3.5 soap:body
3.6 soap:fault
3.7 soap:header
3.8 soap:address
4 HTTP GET 및 POST 바인딩
4.1 HTTP GET/POST 예제
4.2 HTTP GET/POST 바인딩이 WSDL을 확장하는 방법
4.3 http:address
4.4 http:binding
4.5 http:operation
4.6 http:urlEncoded
4.7 http:urlReplacement
5 MIME 바인딩
5.1 MIME 바인딩 예제
5.2 MIME 바인딩이 WSDL을 확장하는 방법
5.3 mime:content
5.4 mime:multipartRelated
5.5 soap:body
5.6 mime:mimeXml
6 참조
A 1 URI에 대한 참고
A 1.1 XML 이름 공간 및 스키마 위치
A 1.2 상대 URI
A 1.3 URI 작성
A 2 네트워크 형식의 WSDL 예제
A 2.1 예제 1
A 3 확장성 요소의 위치
A 4 스키마
A 4.1 WSDL 스키마
A 4.2 SOAP 바인딩 스키마
A 4.3 HTTP 바인딩 스키마
A 4.4 MIME 바인딩 스키마

맨 위로


1. 소개

통신 프로토콜 및 메시지 형식이 웹 커뮤니티에서 표준화됨에 따라, 통신을 어느 정도 구조적인 방법으로 설명하는 것이 점차 가능해지고 중요해지게 되었습니다. WSDL은 네트워크 서비스를 메시지를 교환할 수 있는 통신 종점의 컬렉션으로 설명하는 XML 문법을 정의하여 이러한 필요성을 해결합니다. WSDL 서비스 정의는 분산 시스템에 대한 설명서를 제공하고 응용 프로그램 통신과 관련된 자세한 정보를 자동화할 수 있도록 합니다.

WSDL 문서는 services를 네트워크 종점의 컬렉션 또는 ports로 정의합니다. WSDL에서 종점 및 메시지의 추상 정의는 구체적인 네트워크 구축 또는 데이터 형식 바인딩과는 구분되며 이러한 특성은 추상 정의를 재사용 가능하도록 합니다. 즉, messages는 교환되는 데이터의 추상 설명이고, port typesoperations의 추상 컬렉션입니다. 특정 포트 유형에 대한 구체적인 프로토콜과 데이터 형식 지정은 재사용 가능한 binding을 구성합니다. 포트는 네트워크 주소를 재사용 가능한 바인딩에 연결하여 정의되고, 포트의 컬렉션은 서비스를 정의합니다. 따라서 WSDL 문서는 네트워크 서비스의 정의에서 다음과 같은 요소를 사용합니다.

  • Types? XSD와 같은 특정 형식 시스템을 사용하는 데이터 형식 정의에 대한 컨테이너.
  • Message? 통신할 데이터에 대한 추상적이고 형식화된 정의.
  • Operation? 서비스가 지원하는 동작에 대한 추상적인 설명.
  • Port Type? 하나 이상의 종점에서 지원하는 추상적인 작업 집합.
  • Binding? 특정 포트 유형에 대한 구체적인 프로토콜 및 데이터 형식 지정.
  • Port? 바인딩과 네트워크 주소가 결합되어 정의되는 단일 종점.
  • Service? 관련된 종점의 컬렉션.

이러한 요소들은 2절에서 자세하게 설명합니다. WSDL이 새로운 형식 정의 언어를 도입하는 것은 아니라는 것을 알아두십시오. WSDL은 메시지 형식을 설명하는 다양한 형식 시스템의 필요성을 인식하여 정식의 형식 시스템으로 XML 스키마 규격(XSD)[11]을 지원합니다. 그러나 현재의 메시지 형식을 포함하여 앞으로 사용하게 될 모든 메시지 형식을 설명하는 데 있어 단일 형식 시스템 문법을 기대하기 어렵기 때문에, WSDL은 확장성을 통해 다른 형식의 정의 언어를 사용할 수 있도록 합니다.

또한 WSDL은 일반적인 binding 메커니즘을 정의합니다. 이 메커니즘은 특정 프로토콜이나 데이터 형식 또는 구조를 추상 메시지, 작업 또는 종점에 연결하는 데 사용되고 추상 정의를 재사용할 수 있도록 합니다.

이 규격은 주요 서비스 정의 프레임워크와 함께 다음 프로토콜 및 메시지 형식에 대해 특정 바인딩 확장을 소개합니다.

위의 언어 확장은 이 문서에 정의되어 있지만, 주요 서비스 정의 프레임워크 상단에 계층화 되어있습니다. WSDL을 사용하면 언제든지 다른 바인딩 확장을 사용할 수 있습니다.

맨 위로


1.1 WSDL 문서 예제

다음은 주식 시세를 제공하는 간단한 서비스에 대한 WSDL 정의 예제를 보여 줍니다. 이 서비스는 HTTP상에 SOAP 1.1 프로토콜을 사용하여 구축된 GetLastTradePrice라고 하는 단일 작업을 지원합니다. 요청은 문자열 형식의 증권 시세 표시기 기호를 입력으로 받아, 부동 소수점 형식의 가격을 반환합니다. 이 정의에 사용된 요소에 대한 자세한 설명은 2절(주요 언어) 및 3절(SOAP 바인딩)에서 볼 수 있습니다.

이 예제는 SOAP 인코딩 대신 고정 XML 형식을 사용합니다(SOAP 인코딩을 사용하는 예제는 예제 4를 참조하십시오).

맨 위로


예제 1 HTTP를 통한 SOAP 1.1 요청/응답

<?xml version="1.0"?>
<definitions name="StockQuote"

targetNamespace="http://example.com/stockquote.wsdl"
xmlns:tns="http://example.com/stockquote.wsdl"
xmlns:xsd1="http://example.com/stockquote.xsd"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">

<types>
<schema targetNamespace="http://example.com/stockquote.xsd"
xmlns="http://www.w3.org/1999/XMLSchema">
<element name="TradePriceRequest">
<complexType>
<all>
<element name="tickerSymbol" type="string"/>
</all>
</complexType>
</element>
<element name="TradePrice">
<complexType>
<all>
<element name="price" type="float"/>
</all>
</complexType>
</element>
</schema>
</types>

<message name="GetLastTradePriceInput">
<part name="body" element="xsd1:TradePrice"/>
</message>

<message name="GetLastTradePriceOutput">
<part name="body" element="xsd1:TradePriceResult"/>
</message>

<portType name="StockQuotePortType">
<operation name="GetLastTradePrice">
<input message="tns:GetLastTradePriceInput"/>
<output message="tns:GetLastTradePriceOutput"/>
</operation>
</portType>

<binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="GetLastTradePrice">
<soap:operation soapAction="http://example.com/GetLastTradePrice"/>
<input>
<soap:body use="literal" namespace="http://example.com/stockquote.xsd"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output>
<soap:body use="literal" namespace="http://example.com/stockquote.xsd"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>
</binding>

<service name="StockQuoteService">
<documentation>첫 번째 서비스</documentation>
<port name="StockQuotePort" binding="tns:StockQuoteBinding">
<soap:address location="http://example.com/stockquote"/>
</port>
</service>

</definitions>

맨 위로


1.2 국제 규칙

1. 이 문서에 있는 키워드인 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", 및 "OPTIONAL" 는 RFC-2119 [2]에 설명된 바와 같이 해석됩니다.

2. 다음 이름 공간 접두사는 이 문서 전반에 걸쳐 사용됩니다.

접두사 이름 공간 URI 정의
wsdl http://schemas.xmlsoap.org/wsdl/ WSDL 프레임워크에 대한 WSDL 이름 공간.
soap http://schemas.xmlsoap.org/wsdl/soap/ WSDL SOAP 바인딩에 대한 WSDL 이름 공간.
http http://schemas.xmlsoap.org/wsdl/http/ HTTP GET & POST 바인딩에 대한 WSDL 이름 공간.
mime http://schemas.xmlsoap.org/wsdl/mime/ MIME 바인딩에 대한 WSDL 이름 공간.
soapenc http://schemas.xmlsoap.org/soap/encoding/  SOAP 1.1 [8]에 의해 정의된 인스턴스 이름 공간.
soapenv http://schemas.xmlsoap.org/soap/envelope/  SOAP 1.1 [8]에 의해 정의된 인스턴스 이름 공간.
xsi http://www.w3.org/1999/XMLSchema-instance  XSD[10]에 의해 정의된 인스턴스 이름 공간.
xsd http://www.w3.org/1999/XMLSchema  XSD [10]에 의해 정의된 스키마 이름 공간.
tns (다양함) “this namespace”를 의미하는 (tns) 접두사는 현재 문서를 참조하는 규칙으로 사용됩니다.
(기타) (다양함) 다른 모든 이름 공간 접두사는 단지 예제일 뿐입니다. 특히, “http://example.com”으로 시작하는 URI는 어느 정도 응용 프로그램 종속적이거나 컨텍스트 종속적인 URI[4]를 나타냅니다.

3. 이 규격은 비공식 구문에 사용되어 WSDL 문서의 XML 문법을 설명합니다.

  • 구문은 XML 인스턴스로 나타나지만, 값은 값이라기 보다는 데이터 형식을 나타냅니다.
  • 문자는 "?" (0 또는 1), "*" (0 또는 그 이상의 숫자), "+" (1 또는 그 이상의 숫자)와 같이 요소 및 특성에 추가됩니다.
  • <element…/> 또는 <element…>에서처럼 "…"로 끝나는 요소 이름들은 컨텍스트에 관계 없는 요소/특성이 생략된다는 것을 나타냅니다.
  • 굵게 되어 있는 문법은 이전 문서에 소개되지 않았거나 해당 예제에서 특별히 중요한 부분입니다.
  • <-- extensibility element -->는 XSD 이외인 경우 ##과 같이 어떤 "다른" 이름 공간에서 온 요소에 대한 자리 표시자입니다.
  • 위에 정의된 XML 이름 공간 접두사는 정의되는 요소의 이름 공간을 나타내는 데 사용됩니다.
  • <?xml로 시작되는 예제에는 이 규격을 준수하는 충분한 정보가 있습니다. 다른 예제는 단편적이므로 규격에 맞도록 지정해야 되는 추가 정보가 필요합니다.

XSD 스키마는 WSDL 문법의 공식적인 정의로서 제공됩니다(A4항목을 참조 하시기 바랍니다).

맨 위로


2. 서비스 정의

이 절에서는 WSDL 언어의 주요 요소를 설명합니다. SOAP, HTTP 및 MIME의 바인딩 확장은 3절, 4절 및 5절에서 설명하였습니다.

2.1 WSDL 문서 구조

WSDL 문서는 단순한 정의의 집합입니다. 루트에 definition 요소가 있고 그 안에 정의가 있습니다. 문법은 다음과 같습니다.

<wsdl:definitions name="nmtoken"? targetNamespace="uri"?>

<import namespace="uri" location="uri"/>*

<wsdl:documentation…/> ?

<wsdl:types> ?
<wsdl:documentation…/>?
<xsd:schema…/>*
<-- extensibility element --> *
</wsdl:types>

<wsdl:message name="nmtoken> *
<wsdl:documentation…/>?
<part name="nmtoken" element="qname"? type="qname"?/> *
</wsdl:message>

<wsdl:portType name="nmtoken">*
<wsdl:documentation…/>?
<wsdl:operation name="nmtoken">*
<wsdl:documentation…/> ?
<wsdl:input name="nmtoken"? message="qname">?
<wsdl:documentation…/> ?
</wsdl:input>
<wsdl:output name="nmtoken"? message="qname">?
<wsdl:documentation…/> ?
</wsdl:output>
<wsdl:fault name="nmtoken" message="qname"> *
<wsdl:documentation…/> ?
</wsdl:fault>
</wsdl:operation>
</wsdl:portType>

<wsdl:binding name="nmtoken" type="qname">*
<wsdl:documentation…/>?
<-- extensibility element --> *
<wsdl:operation name="nmtoken">*
<wsdl:documentation…/> ?
<-- extensibility element --> *
<wsdl:input name="nmtoken"?> ?
<wsdl:documentation…/> ?
<-- extensibility element -->
</wsdl:input>
<wsdl:output name="nmtoken"?> ?
<wsdl:documentation…/> ?
<-- extensibility element --> *
</wsdl:output>
<wsdl:fault name="nmtoken"> *
<wsdl:documentation…/> ?
<-- extensibility element --> *
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>

<wsdl:service name="nmtoken"> *
<wsdl:documentation…/>?
<wsdl:port name="nmtoken" binding="qname"> *
<wsdl:documentation…/> ?
<-- extensibility element -->
</wsdl:port>
<-- extensibility element -->
</wsdl:service>

<-- extensibility element --> *

</wsdl:definitions>

서비스는 다섯 개의 중요한 요소를 사용하여 정의됩니다.

  • types는 교환된 메시지를 설명하는 데 사용된 데이터 형식 정의를 제공합니다.
  • message는 전송되는 데이터의 추상 정의를 나타냅니다. 메시지는 논리적인 부분으로 이루어져 있으며 각 부분은 특정 형식 시스템 내의 정의와 연관되어 있습니다.
  • portType은 추상 작업의 집합이며 각 작업은 입력 메시지 및 출력 메시지를 참조합니다.
  • binding은 특정 portType에 의해 정의된 메시지 및 작업에 대해 구체적인 프로토콜과 데이터 형식을 지정합니다.
  • port는 바인딩에 대해 주소를 지정하기 때문에 단일 통신 종점을 정의합니다.
  • service는 관련된 포트의 집합을 집계하는 데 사용됩니다.

2.2절에서 2.7절은 이러한 요소를 설명합니다. 이 절의 나머지 부분은 문서 명명, 문서 정의 참조, 언어 확장 사용 및 컨텍스트 설명서 추가에 대해 WSDL로 소개된 규칙을 설명합니다.

맨 위로


2.1.1 문서 명명 및 연결

WSDL 문서는 간단한 형태의 설명서로 제공되는 NCNAME 형식의 선택적인 name 특성으로 지정될 수 있습니다. 또한 URI 형식의 targetNamespace 특성을 지정할 수도 있습니다. URI는 상대 URI일 수 없습니다.

WSDL은 import 문을 사용하여 문서 locationnamespace를 연결할 수 있도록 합니다.

<definitions…>
<import namespace="uri" location="uri"/> *
</definitions>

WSDL 정의 참조는 QName 을 사용하여 만들어집니다. WSDL 문서에 포함된 다음과 같은 정의 형식이 참조될 수도 있습니다.

  • WSDL 정의: service, port, message, bindings, 및 portType
  • 기타 정의: 추가 정의가 확장성을 통해 추가되는 경우, 이 정의는 QName 연결을 사용합니다.

위에 나열된 WSDL 정의 형식은 자체 이름 범위를 가지고 있습니다. 즉, port 이름과 message 이름은 충돌하지 않습니다. 이름 범위내에 있는 이름은 WSDL 문서 내에서 고유해야 합니다.

WSDL에서 QNames 확인은 XML 스키마 규격[11]으로 설명된 QNames 확인과 유사합니다.

맨 위로


2.1.2 제작 스타일

import 요소를 사용하여 서비스 정의의 서로 다른 요소들을 별도의 문서로 분리하여 필요할 때 가져올 수 있습니다. 이 기능은 서비스의 추상화 수준에 따라 정의를 분리하여 서비스 정의를 더 명확하게 작성할 수 있도록 도와 줍니다. 또한 모든 종류의 서비스 정의를 재사용하는 기능을 최대화합니다. 따라서 이러한 방법으로 구조화된 WSDL 문서는 사용 및 유지 관리가 쉽습니다. 아래의 예제 2는 예제 1에 나타난 서비스를 정의하는 제작 스타일의 사용 방법을 보여 줍니다. 여기서는 정의를 데이터 형식 정의, 추상 정의 및 특정 서비스 바인딩의 세 개 문서로 분리하였습니다. 이 메커니즘의 사용은 이 규격에 정의된 언어 요소만 사용하는 예제에 명시적으로 나타난 정의에만 제한되지는 않습니다. 추가 언어 확장을 기반으로 하는 다른 형식의 정의는 유사한 방법으로 인코드되고 다시 사용될 수 있습니다.

예제 2. 예제 1의 서비스에 대한 대체 제작 스타일

http://example.com/stockquote/stockquote.xsd

<?xml version="1.0"?>
<schema targetNamespace="http://example.com/stockquote/schemas"
xmlns="http://www.w3.org/2000/10/XMLSchema">

<element name="TradePriceRequest">
<complexType>
<all>
<element name="tickerSymbol" type="string"/>
</all>
</complexType>
</element>
<element name="TradePrice">
<complexType>
<all>
<element name="price" type="float"/>
</all>
</complexType>
</element>
</schema>

http://example.com/stockquote/stockquote.wsdI

<?xml version="1.0"?>
<definitions name="StockQuote"

targetNamespace="http://example.com/stockquote/definitions"
xmlns:tns="http://example.com/stockquote/definitions"
xmlns:xsd1="http://example.com/stockquote/schemas"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">

<import namespace="http://example.com/stockquote/schemas"
location="http://example.com/stockquote/stockquote.xsd"/>


<message name="GetLastTradePriceRequest">
<part name="body"element="xsd1:GetLastTradePrice"/>
</message>

<message name="GetLastTradePriceResponse">
<part name="body"element="xsd1:GetLastTradePriceResult"/>
</message>

<portType name="StockQuotePortType">
<operation name="GetLastTradePrice">
<input message="tns:GetLastTradePriceRequest"/>
<output message="tns:GetLastTradePriceResponse"/>
</operation>
</portType>
</definitions>

http://example.com/stockquote/stockquoteservice.wsdI

<?xml version="1.0"?>
<definitions name="StockQuote"

targetNamespace="http://example.com/stockquote/service"
xmlns:tns="http://example.com/stockquote/service"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:defs="http://example.com/stockquote/definitions"
xmlns="http://schemas.xmlsoap.org/wsdl/">

<import namespace="http://example.com/stockquote/definitions"
location="http://example.com/stockquote/stockquote.wsdl"/>


<binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType">
<soap:binding style="document"/>
<operation name="GetLastTradePrice">
<soap:operation soapAction="http://my.org/GetLastTradePrice"/>
</operation>>
</binding>

<service name="StockQuoteService">
<documentation>첫 번째 서비스</documentation>
<port name="StockQuotePort" binding="tns:StockQuoteBinding">
<soap:address location="http://my.org/stockquote"/>
</port>
</service>
</definitions>

맨 위로


2.1.3 언어 확장성 및 바인딩

WSDL에서 바인딩이라는 용어는 프로토콜 또는 데이터 형식 정보와 message, operation 또는 portType과 같은 추상 엔티티를 연결하는 과정을 나타냅니다. WSDL는 WSDL로 정의된 다양한 요소 아래 특정 기술(확장성 요소)을 나타내는 요소를 허용합니다. 이러한 확장성은 일반적으로 특정 프로토콜 또는 메시지 형식에 대한 바인딩 정보를 지정하는 데 사용되지만 이러한 사용에 제한되지 않습니다. 확장성 요소는 WSDL 이름 공간과는 다른 XML 이름 공간을 사용해야 합니다. 확장성 요소가 나타날 수 있는 문서에서 특정 위치는 부록 A3에 자세히 설명되어 있습니다.

확장성 요소는 일반적으로 몇몇 특정 기술 관련 바인딩을 지정하는 데 사용됩니다. 통신에 기술 관련 바인딩 기능이 필요한지 또는 선택적인지를 구별하기 위해 확장성 요소는 해당 요소에 부울 형식의 wsdl:required 특성을 배치할 수도 있습니다. 필요한 기본값은 false입니다. 필요한 특성은 이름 공간 "http://schemas.xmlsoap.org/wsdl/"에서 정의됩니다.

확장성 요소를 사용하면 기본 WSDL 규격을 개정하지 않고 네트워크와 메시지 프로토콜 영역을 새로 바꿀 수 있습니다. WSDL은 이러한 프로토콜을 정의하는 규격이 프로토콜이나 형식을 설명하는 데 사용하는 필수 WSDL 확장도 정의할 것을 권장합니다.

확장성 요소에 대한 예제를 보려면 3절, 4절 및 5절을 참조하십시오.

맨 위로


2.1.4 설명서

WSDL은 육안으로 읽을 수 있는 설명서의 컨테이너로서 선택적인 wsdl:document 요소를 사용합니다. 요소의 컨텐트는 임의의 텍스트 및 요소입니다(XSD의 "mixed"). 설명서 요소는 모든 WSDL 언어 요소 안에 허용됩니다.

2.2 형식

types 요소는 교환된 메시지와 관련된 데이터 형식 정의를 묶습니다. 상호 운영성 및 플랫폼 중립성을 최대화 하기 위해 WSDL은 정식의 형식 시스템으로서 XSD를 사용하고 이것을 기본적인 형식 시스템으로 처리합니다.

<definitions…>
<types>
<xsd:schema…/>*
</types>
</definitions>

XSD 형식 시스템은 결과 네트워크 형식이 실제 XML인지 또는 결과 XSD 스키마가 특정 네트워크 형식을 확인하는지 여부에 관계 없이 메시지의 형식을 정의하는 데 사용될 수 있습니다. 특히, 동일한 메시지에 대해 다중 바인딩이 있거나 하나의 바인딩만 존재하지만 해당 바인딩 형식이 널리 사용되는 형식 시스템을 가지지 않는 경우에 유용합니다. 이러한 경우, XSD를 사용하여 추상 형식을 인코딩하기 위한 바람직한 접근 방법은 다음과 같습니다.

  • 특성이 아닌 요소 폼을 사용합니다.
  • 네트워크 인코딩에 고유한 특성이나 요소를 포함하지 않습니다(즉, 메시지의 추상 컨텐트와 무관함). soap:root, soap:encodingStyle, xmi:id, xmi:name 등이 이에 해당하는 예입니다.
  • 배열 형식을 모델링하려면 결과 폼이 SOAP v1.1 문서의 5절에 지정된 인코딩을 실제 사용하는지 여부와 관계 없이, Soap:Array 형식을 사용합니다. 배열 형식에 대해 ArrayOfXXX 이름을 사용합니다(여기서 XXX는 배열에서 항목의 형식임).
  • xsd:anyType 형식을 사용하여 모든 형식을 가질 수 있는 필드/매개 변수를 표현합니다.

하지만 현재의 추상적인 형식을 포함하여 앞으로 사용하게 될 모든 추상적인 형식을 설명하는 데 사용할 단일 형식의 시스템 문법을 기대하기 어렵기 때문에, WSDL은 형식 시스템이 확장성 요소를 통해 추가될 수 있도록 합니다. 확장성 요소는 types 요소 아래 나타나며 사용되는 형식 정의 시스템을 식별하고 형식 정의에 대해 XML 컨테이너 요소를 제공합니다. 이 요소의 역할은 XML 스키마 언어의 schema 요소의 역할과 비교할 수 있습니다.

<definitions…>
<types>
<-- type-system extensibility element --> *
</types>
</definitions>

맨 위로


2.3 메시지

메시지는 하나 이상의 논리적인 parts로 구성되어 있습니다. 각 부분은 메시지 형식 특성을 사용하는 특정 형식 시스템의 형식과 연관되어 있습니다. 메시지 형식의 특성 집합은 확장할 수 있습니다. WSDL은 XSD에 사용되는 몇몇 메시지 형식의 특성을 정의합니다.

  • element. QName을 사용하는 XSD 요소를 참조합니다.
  • type. QName을 사용하는 XSD simpleType 또는 complexType을 참조합니다.

WSDL의 이름 공간과는 다른 이름 공간을 사용하면 다른 메시지 형식 특성이 정의될 수도 있습니다. 확장성 요소 바인딩에도 메시지 형식 특성이 사용됩니다.

메시지를 정의하는 구문은 다음과 같습니다. 사용된 형식 시스템에 따라 다양한 메시지 형식 특성은 굵게 표시되어 있습니다.

<definitions…>
<message name="nmtoken"> *
<part name="nmtoken"? element="qname" type="qname"?/> *
</message>
</definitions>

메시지 name 특성은 해당 WSDL 문서에 정의된 모든 message 간에 고유한 이름을 제공합니다.

부분 name 특성은 해당 메시지의 모든 부분 간에 고유한 이름을 제공합니다.

맨 위로


2.3.1 메시지 부분

part는 message의 논리적인 추상 컨텐트를 설명하는 융통성 있는 메커니즘입니다. 바인딩은 부분에 관한 바인딩별 정보를 지정하기 위해 부분의 이름을 참조할 수 있습니다. 예를 들어, RPC를 사용하기 위해 메시지를 정의하는 경우, 부분은 메시지에 매개 변수를 나타낼 수도 있습니다. 하지만 부분의 실제 의미를 결정하기 위해서는 반드시 바인딩을 점검해야 합니다.

다중 부분 요소는 메시지에 여러 개의 논리적 단위가 있는 경우에 사용됩니다. 예를 들어, 다음 메시지는 주문서와 고객으로 구성되어 있습니다.

<definitions .... >

<types>

<schema .... >

<element name="PO" type="tns:POType"/>

<complexType name="POType">

<all>

<element name="id" type="string/>

<element name="name" type="string"/>

<element name="items">

<complexType>

<all>

<element name="item" type="tns:Item" minOccurs="0"
maxOccurs="unbounded"/>

</all>

</complexType>

</element>

</all>

</complexType>



<complexType name="Item">

<all>

<element name="quantity" type="int"/>

<element name="product" type="string"/>

</all>

</complexType>

<element name="Invoice" type="tns:InvoiceType"/>

<complexType name="InvoiceType">

<all>

<element name="id" type="string"/>

</all>

</complexType>

</schema>

</types>



<message name="PO">

<part name="po" element="tns:PO"/>

<part name="invoice" element="tns:Invoice"/>

</message>

</definitions>

하지만, 메시지 컨텐트가 너무 복잡한 경우에는 대체 구문을 사용하여 형식 시스템을 직접 사용하는 복합 메시지 구조를 지정할 수 있습니다. 다음 예제에서, 본문은 주문서 또는 고객 집합이 될 수 있습니다.

<definitions .... >
<types>
<schema .... >
<complexType name="POType">
<all>
<element name="id" type="string/>
<element name="name" type="string"/>
<element name="items">
<complexType>
<all>
<element name="item" type="tns:Item" minOccurs="0"
maxOccurs="unbounded"/>
</all>
</complexType>
</element>
</all>
</complexType>

<complexType name="Item">
<all>
<element name="quantity" type="int"/>
<element name="product" type="string"/>
</all>
</complexType>
<complexType name="InvoiceType">
<all>
<element name="id" type="string"/>
</all>
</complexType>

<complexType name="Composite">
<choice>
<element name="PO" minOccurs="1" maxOccurs="1" type="tns:POType"/>
<element name="Invoice" minOccurs="0" maxOccurs="unbounded"
type="tns:InvoiceType"/>

</choice>
</complexType>
</schema>
</types>

<message name="PO">
<part name="composite" type="tns:Composite"/>
</message>
</definitions>

맨 위로


2.3.2 추상적인 메시지와 구체적인 메시지

메시지 정의는 항상 메시지 컨텐트의 추상 정의로 간주합니다. 메시지 바인딩은 추상 컨텐트가 구체적인 서식에 매핑되는 방법을 설명합니다. 경우에 따라, 추상 정의가 구체적인 표현과 매우 흡사하거나 하나 이상의 바인딩과 정확히 일치하기도 합니다. 따라서 이러한 바인딩은 매핑 정보를 거의 제공하지 않습니다. 하지만 동일한 메시지 정의의 다른 바인딩은 확장 가능한 매핑 정보가 필요하기도 합니다. 따라서 바인딩을 점검해야 메시지가 실제로 "추상화되는 방법"을 결정할 수 있습니다.

2.4 포트 형식

포트 형식은 추상 작업 및 포함된 추상 메시지의 명명된 집합입니다.

<wsdl:definitions…>
<wsdl:portType name="nmtoken">
<wsdl:operation name="nmtoken"…/> *
</wsdl:portType>
</wsdl:definitions>

포트 형식의 name 특성은 해당 WSDL 문서에 정의된 모든 포트 형식에 고유한 이름을 제공합니다.

작업은 name 특성을 통해 명명됩니다.

WSDL에는 종점에서 지원할 수 있는 네 가지 전송 방식이 있습니다.

  • 단방향. 종점이 메시지를 받습니다.
  • 요청-응답. 종점이 메시지를 받고 관련된 메시지를 보냅니다.
  • 검색-응답. 종점이 메시지를 보내고 관련된 메시지를 받습니다.
  • 알림. 종점이 메시지를 보냅니다.

WSDL은 이러한 전송 방식을 operations로 참조합니다. 요청/응답 또는 검색/응답 작업이 두 개의 단방향 메시지를 사용하여 추상적으로 모델링되더라도, 이 작업을 근본적인 작업의 형식으로서 모델링하는 것이 유용하며 그 이유는 다음과 같습니다.

  • 요청/응답 또는 검색/응답 작업은 일반적입니다.
  • 더 복잡한 이동 정보를 도입하지 않고도 순서가 상호 연관될 수 있습니다.
  • 몇몇 종점은 메시지가 동기화된 요청/응답 작업의 결과일 경우에만 메시지를 받을 수 있습니다.
  • 단순한 흐름은 흐름 정의가 필요한 시점에 이러한 방식으로부터 알고리즘적으로 파생될 수 있습니다.

요청/응답 또는 검색/응답이 WSDL 문서에 논리적으로 상호 연관되어 있어도, 지정된 바인딩은 구체적인 상호 관련 정보를 설명합니다. 예를 들어, 요청 및 응답 메시지는 하나 또는 두 개의 실제 네트워크 통신의 부분으로 교환될 수도 있습니다.

기본 WSDL 구조가 4가지 전송 방식의 바인딩을 지원하지만 WSDL은 단방향과 요청-응답 방식의 바인딩만 정의합니다. 검색-응답 또는 알림용 프로토콜을 정의하는 규격이 이러한 방식을 사용할 수 있는 WSDL 바인딩 확장도 포함할 것으로 기대하고 있습니다.

작업은 QName 형식의 message 특성을 사용하여 포함된 메시지를 참조합니다. 이 특성은 WSDL에 의해 정의된 연결 규칙을 따릅니다(2.1.1절 참조).

맨 위로


2.4.1 단방향 작업

단방향 작업의 문법은 다음과 같습니다.

<wsdl:definitions…> <wsdl:portType…> *
<wsdl:operation name="nmtoken">
<wsdl:input name="nmtoken"? message="qname"/>
</wsdl:operation>
</wsdl:portType >
</wsdl:definitions>

input 요소는 단방향 작업에 대한 추상적인 메시지 형식을 지정합니다.

2.4.2 요청-응답 작업

요청-응답 작업의 문법은 다음과 같습니다.

<wsdl:definitions…>
<wsdl:portType…> *
<wsdl:operation name="nmtoken" parameterOrder="nmtokens">
<wsdl:input name="nmtoken"? message="qname"/>
<wsdl:output name="nmtoken"? message="qname"/>
<wsdl:fault name="nmtoken" message="qname"/>*
</wsdl:operation>
</wsdl:portType >
</wsdl:definitions>

input 및 output 요소는 각각 요청과 응답에 대한 추상적인 메시지 형식을 지정합니다. 선택적인 fault 요소는 프로토콜에 한정된 메시지뿐만 아니라 작업의 결과로서 출력되는 모든 오류 메시지에 대한 추상적인 메시지 형식을 지정합니다.

요청-응답 작업은 추상 개념입니다. 특정 바인딩은 HTTP 요청/응답과 같은 단일 통신 내에서 또는 HTTP 요청과 같은 두 개의 독립적인 통신으로서의 메시지를 실제로 보내는 방법을 결정하는 데 사용됩니다.

맨 위로


2.4.3 검색-응답 작업

검색-응답 작업의 문법은 다음과 같습니다.

<wsdl:definitions…>
<wsdl:portType…> *
<wsdl:operation name="nmtoken" parameterOrder="nmtokens">
<wsdl:output name="nmtoken"? message="qname"/>
<wsdl:input name="nmtoken"? message="qname"/>
<wsdl:fault name="nmtoken" message="qname"/>*
</wsdl:operation>
</wsdl:portType >
</wsdl:definitions>

output 및 input 요소는 각각 검색된 요청 메시지와 응답 메시지에 대해 추상적인 메시지 형식을 지정합니다. 선택적인 fault 요소는 프로토콜에 한정된 메시지뿐만 아니라 작업의 결과로서 출력되는 모든 오류 메시지에 추상적인 메시지 형식을 지정합니다.

요청-응답 작업은 추상 개념입니다. 특정 바인딩은 HTTP 요청/응답과 같은 단일 통신 내에서 또는 HTTP 요청과 같은 두 개의 독립적인 통신으로서의 메시지를 실제로 보내는 방법을 결정하는 데 사용됩니다.

맨 위로


2.4.4 알림 작업

단방향 작업의 문법은 다음과 같습니다.

<wsdl:definitions…>
<wsdl:portType…> *
<wsdl:operation name="nmtoken">
<wsdl:output name="nmtoken"? message="qname"/>
</wsdl:operation>
</wsdl:portType >
</wsdl:definitions>

output 요소는 알림 작업에 추상적인 메시지 형식을 지정합니다.

2.4.5 작업 내 요소의 이름

input 및 output 요소의 name 특성은 이를 포함하는 포트 형식 내에서 모든 input 및 output 요소 간에 고유한 이름을 제공합니다.

작업 중 각 input 및 output 요소의 이름을 지정할 필요가 없도록 하기 위해 WSDL이 작업 이름을 기반으로 하는 몇몇 기본값을 제공합니다. name 특성이 단방향 또는 알림 메시지에 지정되지 않은 경우 기본값은 작업 이름이 됩니다. name 특성이 요청-응답 또는 검색-응답 작업의 input 또는 output 메시지에 지정되지 않은 경우, "Request"/"Solicit" 또는 "Response"가 각각 추가된 작업 이름이 기본값이 됩니다.

각 fault 요소는 바인딩이 fault 메시지의 구체적인 서식을 지정하도록 명명되어야 합니다. fault 요소의 이름은 작업에 대해 정의된 fault의 집합 내에서 고유합니다.

맨 위로


2.4.6 작업 내 매개 변수 순서

작업은 RPC 방식의 바인딩과 함께 사용될지의 여부를 지정하지 않습니다. 하지만 작업과 RPC 바인딩을 함께 사용하는 경우에는 원래 RPC 함수의 서명을 캡처하는 것이 유용합니다. 따라서 요청-응답 또는 검색-응답 작업은 nmtokens 형식의 parameterOrder 특성을 통해 매개 변수 이름 목록을 지정할 수도 있습니다. 특성 값은 단일 공백으로 분리된 메시지 부분의 이름 목록입니다. 명명된 부분은 다음 규칙을 반드시 준수해야 합니다.

  • 부분의 순서는 RPC 서명에서 매개 변수의 순서를 반영하도록 명명됩니다.
  • return 값 부분은 목록에 없습니다.
  • 부분 이름이 input 메시지와 output 메시지에 모두 나타나면 in/out 매개 변수입니다.
  • 부분 이름이 input 메시지에만 나타나면 in 매개 변수입니다.
  • 부분 이름이 output 메시지에만 나타나면 out 매개 변수입니다.

이 정보는 "참고"로 제공되는 것이므로 RPC 서명과는 관계 없는 경우에는 무시해도 됩니다. 또한 작업이 RPC 방식 바인딩과 함께 사용되는 경우에도 이 정보 제공이 필요하지 않습니다.

맨 위로


2.5 바인딩

바인딩은 특정 portType에 의해 정의된 작업 및 메시지에 대해 메시지 형식 및 프로토콜 정보를 정의합니다. 지정된 portType에 대한 바인딩 수는 제한이 없습니다. 바인딩의 문법은 다음과 같습니다.

<wsdl:definitions…>
<wsdl:binding name="nmtoken" type="qname"> *
<-- extensibility element (1) --> *
<wsdl:operation name="nmtoken"> *
<-- extensibility element (2) --> *
<wsdl:input name="nmtoken"?> ?
<-- extensibility element (3) -->
</wsdl:input>
<wsdl:output name="nmtoken"?> ?
<-- extensibility element (4) --> *
</wsdl:output>
<wsdl:fault name="nmtoken"> *
<-- extensibility element (5) --> *
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
</wsdl:definitions>

name 특성은 이를 포함하는 WSDL 문서에 정의된 모든 바인딩에 고유한 이름을 제공합니다.

바인딩은 type 특성을 사용하여 바인드하는 portType을 참조합니다. 이 QName 값은 WSDL에 의해 정의된 연결 규칙을 따릅니다(2.1.1절 참조).

바인딩의 operation, input, output 및 fault 요소는 portType 내에서 정확히 작동하는 각 요소의 name 특성을 사용하는 해당 portType 요소와 상호 연관되어 있습니다(2.4.5절 참조).

바인딩 확장성 요소는 input (3), output (4) 및 fault 메시지 (5)에 대해 구체적인 문법을 지정하는 데 사용됩니다. 바인딩 단위 정보 (1)뿐만 아니라, 작업 단위 바인딩 정보 (2)도 지정됩니다.

바인딩 내의 작업은 바인딩의 portType 내에서 같은 이름을 가진 작업에 대한 바인딩 정보를 지정합니다. 예를 들어, 메서드 이름을 오버로드하는 경우처럼 작업 이름은 고유할 필요가 없기 때문에 작업 바인딩 요소의 이름 특성만으로 작업을 고유하게 식별하지 못할 수 있습니다. 이러한 경우에는 해당 wsdl:input과 wsdl:output 요소의 name 특성을 제공하여 올바른 작업을 식별하도록 해야 합니다.

한개의 바인딩은 한개의 프로토콜만 지정해야 합니다.

바인딩은 주소 정보를 지정하지 않을 수도 있습니다.

맨 위로


2.6 포트

포트는 바인딩에 대해 단일 주소를 지정하여 개별적인 종점을 정의합니다.

<wsdl:definitions…>
<wsdl:service…> *
<wsdl:port name="nmtoken" binding="qname"> *
<-- extensibility element (1) -->
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

name 특성은 이를 포함하는 WSDL 문서에 정의된 모든 포트에 고유한 이름을 제공합니다.

QName 형식의 binding 특성은 WSDL에 의해 정의된 연결 규칙을 사용하는 바인딩을 참조합니다(2.1.1절 참조).

바인딩 확장성 요소 (1)는 포트에 대해 주소 정보를 지정하는 데 사용됩니다.

한개의 포트는 두개 이상의 주소를 지정하지 않을 수도 있습니다.

포트는 주소 정보가 아닌 바인딩 정보를 전혀 지정하지 않을 수도 있습니다.

맨 위로


2.7 서비스

서비스는 관련된 포트의 집합을 그룹화합니다.

<wsdl:definitions…>
<wsdl:service name="nmtoken"> *
<wsdl:port…/>*
</wsdl:service>
</wsdl:definitions>

name 특성은 이를 포함하는 WSDL 문서에 정의된 모든 서비스에 고유 이름을 제공합니다.

서비스 내의 포트는 다음과 같은 관계를 가지고 있습니다.

  • 포트 간에 서로 통신하지 않습니다(예: 한 포트의 output은 다른 포트의 input이 될 수 없습니다).
  • 별도의 바인딩 및 주소를 사용하면서도 한개의 서비스에 포트 형식을 공유하는 여러 개의 포트가 있는 경우 포트는 대체 요소가 됩니다. 각 포트는 기능적으로 동등한 동작을 제공합니다(전송 및 메시지 형식은 각 바인딩에 의해 제한됨). 이 기능으로 WSDL 사용자는 프로토콜, 거리 등과 같은 몇몇 조건을 기반으로 하여 통신할 수 있는 특정 포트를 선택할 수 있습니다.
  • 이 포트를 확인하여 서비스의 포트의 형식을 결정할 수 있습니다. 이렇게 하면 WSDL 문서의 고객은 이 문서가 여러 개의 포트를 지원하는지의 여부에 따라 특정 서비스와 통신할지를 결정할 수 있습니다. 이 기능은 포트 형식의 작업간에 몇몇 묵시적인 관계가 있는 경우에 유용하며, 특정 작업을 수행하기 위해서는 포트 형식의 전체 집합이 반드시 표시되어야 합니다.

맨 위로


3. SOAP 바인딩

WSDL은 다음과 같은 프로토콜별 정보의 규격을 지원하는 SOAP 1.1 종점에 대한 바인딩을 포함합니다.

  • 바인딩과 SOAP 1.1 프로토콜과의 바운드 표시.
  • SOAP 종점에 대한 주소 지정 방법.
  • SOAP의 HTTP 바인딩에 대한 SOAPAction HTTP 헤더의 URI.
  • SOAP Envelope의 일부로서 전송되는 헤더의 정의 목록.
  • XSD의 SOAP 루트 지정 방법.

SOAP 바인딩의 집합은 진화하기 때문에 이 바인딩 문법은 아주 확실한 규격은 아닙니다. 추가 SOAP 바인딩은 반드시 이 문법의 개념에서 파생됩니다. 예를 들면 다음과 같습니다.

  • URI 주소 지정 스키마를 사용하지 않는 SOAP 바인딩은 3.8절에 정의된 soap:address 요소를 재배치하여 다른 주소 지정 스키마를 대체 사용합니다.
  • SOAPAction이 필요 없는 SOAP 바인딩은 3.4절에 정의된 soapAction 특성을 생략합니다.

맨 위로


3.1 SOAP 예제

다음 예제에서 SubscribeToQuotes SOAP 1.1 단방향 메시지는 SMTP 바인딩을 통해 StockQuote 서비스로 전달됩니다. 요청은 문자열 형식의 증권 시세 표시기 기호를 입력으로 받고, 대체 URI를 정의하는 헤더를 포함합니다.

예제 3. SOAP 헤더를 사용하는 SMTP에서의 단방향 작업의 SOAP 바인딩

<?xml version="1.0"?>
<definitions name="StockQuote"
targetNamespace="http://example.com/stockquote.wsdl"
xmlns:tns="http://example.com/stockquote.wsdl"
xmlns:xsd="http://www.w3.org/2000/10/XMLSchema"
xmlns:xsd1="http://example.com/stockquote.xsd"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">

<message name="GetTradePriceInput">
<part name="tickerSymbol" element="xsd:string"/>
<part name="time" element="xsd:timeInstant"/>
</message>

<message name="GetTradePriceOutput">
<part name="result" type="xsd:float"/>
</message>

<portType name="StockQuotePortType">
<operation name="GetTradePrice">
<input message="tns:GetTradePriceInput"/>
<output message="tns:GetTradePriceOutput"/>
</operation>
</portType>

<binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="GetTradePrice">
<soap:operation soapAction="http://example.com/GetTradePrice"/>
<input>
<soap:body use="encoded" namespace="http://example.com/stockquote"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output>
<soap:body use="encoded" namespace="http://example.com/stockquote"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>>
</binding>

<service name="StockQuoteService">
<documentation>My first service</documentation>
<port name="StockQuotePort" binding="tns:StockQuoteBinding">
<soap:address location="http://example.com/stockquote"/>
</port>
</service>
</definitions>

이 예제는 GetLastTradePrice SOAP 1.1 요청이 SOAP 1.1 HTTP 바인딩을 통해 StockQuote 서비스로 전달될 수도 있음을 설명합니다. 이 요청은 문자열 형식의 주식 시세 표시기 기호 즉, timeInstant 형식의 time을 입력 받아 SOAP 응답에서 부동 소수점 형식으로 된 가격을 반환합니다.

예제 4. HTTP에서의 요청-응답 RPC 작업의 SOAP 바인딩

<?xml version="1.0"?>
<definitions name="StockQuote"

targetNamespace="http://example.com/stockquote.wsdl"
xmlns:tns="http://example.com/stockquote.wsdl"
xmlns:xsd1="http://example.com/stockquote.xsd"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">

<message name="GetLastTradePriceRequest">
<part name="tickerSymbol" element="xsd:string"/>
<part name="time" element="xsd:timeInstant"/>
</message>

<message name="GetLastTradePriceResponse">
<part name="result" type="xsd:float"/>
</message>

<portType name="StockQuotePortType">
<operation name="GetLastTradePrice">
<input message="tns:GetLastTradePriceRequest"/>
<output message="tns:GetLastTradePriceResponse"/>
</operation>
</portType>

<binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="GetLastTradePrice">
<soap:operation soapAction="http://example.com/GetLastTradePrice"/>
<input>
<soap:body use="encoded" namespace="http://example.com/stockquote"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output>
<soap:body use="encoded" namespace="http://example.com/stockquote"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>>
</binding>

<service name="StockQuoteService">
<documentation>첫 번째 서비스</documentation>
<port name="StockQuotePort" binding="tns:StockQuoteBinding">
<soap:address location="http://example.com/stockquote"/>
</port>
</service>
</definitions>

이 예제에서는 SOAP 1.1 HTTP 바인딩을 통해 StockQuote 서비스로 GetTradePrices SOAP 1.1 요청을 전송할 수 있음을 설명합니다. 요청은 시작과 종료 시간이 포함된 TimePeriod 구조를 정의한 응용 프로그램인 주식 시세 기호 문자열의 입력을 받아 해당 기간 내에 서비스가 기록한 주식 시세 배열뿐만 아니라 SOAP 응답으로 기록된 주기를 반환합니다. 이 서비스에 대응하는 RPC 서명은 매개 변수 tickerSymbol 및 timePeriod와 함께 출력 매개 변수 주기를 가지며 부동 소수점 배열을 반환합니다.

예제 5. HTTP에서의 요청-응답 RPC 작업의 SOAP 바인딩

<?xml version="1.0"?>
<definitions name="StockQuote"

targetNamespace="http://example.com/stockquote.wsdl"
xmlns:tns="http://example.com/stockquote.wsdl"
xmlns:xsd="http://www.w3.org/2000/10/XMLSchema"
xmlns:xsd1="http://example.com/stockquote/schema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns="http://schemas.xmlsoap.org/wsdl/">

<types>
<schema targetNamespace="http://example.com/stockquote/schema"
xmlns="http://www.w3.org/2000/10/XMLSchema">
<complexType name="TimePeriod">
<all>
<element name="startTime" type="xsd:timeInstant"/>
<element name="endTime" type="xsd:timeInstant"/>
</all>
</complexType>
<complexType name="ArrayOfFloat">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:float[]"/>
</restriction>
</complexContent>
</complexType>
</schema>
</types>

<message name="GetTradePricesInput">
<part name="tickerSymbol" element="xsd:string"/>
<part name="timePeriod" element="xsd1:TimePeriod"/>
</message>

<message name="GetTradePricesOutput">
<part name="result" type="xsd1:ArrayOfFloat"/>
<part name="frequency" type="xsd:float"/>
</message>

<portType name="StockQuotePortType">
<operation name="GetLastTradePrice"
parameterOrder="tickerSymbol timePeriod frequency">
<input message="tns:GetTradePricesInput"/>
<output message="tns:GetTradePricesOutput"/>
</operation>
</portType>

<binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="GetTradePrices">
<soap:operation soapAction="http://example.com/GetTradePrices"/>
<input>
<soap:body use="encoded" namespace="http://example.com/stockquote"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output>
<soap:body use="encoded" namespace="http://example.com/stockquote"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>>
</binding>

<service name="StockQuoteService">
<documentation>My first service</documentation>
<port name="StockQuotePort" binding="tns:StockQuoteBinding">
<soap:address location="http://example.com/stockquote"/>
</port>
</service>
</definitions>

맨 위로


3.2 SOAP 바인딩이 WSDL을 확장하는 방법

SOAP 바인딩은 다음과 같은 확장성 요소로 WSDL을 확장합니다.

<definitions .... >
<binding .... >
<soap:binding style="rpc|document" transport="uri">
<operation .... >
<soap:operation soapAction="uri"? style="rpc|document"?>?
<input>
<soap:body parts="nmtokens"? use="literal|encoded"
encodingStyle="uri-list"? namespace="uri"?>

<soap:header message="qname" part="nmtoken" use="literal|encoded"
encodingStyle="uri-list"? namespace="uri"?>*
<soap:headerfault message="qname" part="nmtoken" use="literal|encoded"
encodingStyle="uri-list"? namespace="uri"?/>*
<soap:header>
</input>
<output>
<soap:body parts="nmtokens"? use="literal|encoded"
encodingStyle="uri-list"? namespace="uri"?>

<soap:header message="qname" part="nmtoken" use="literal|encoded"
encodingStyle="uri-list"? namespace="uri"?>*
<soap:headerfault message="qname" part="nmtoken" use="literal|encoded"
encodingStyle="uri-list"? namespace="uri"?/>*
<soap:header>
</output>
<fault>*
<soap:fault name="nmtoken" use="literal|encoded"
encodingStyle="uri-list"? namespace="uri"?>

</fault>
</operation>
</binding>

<port .... >
<soap:address location="uri"/>
</port>
</definitions>

SOAP 바인딩의 각 확장 요소는 다음 절에 설명하였습니다.

맨 위로


3.3 soap:binding

Envelope, Header 및 Body와 같은 SOAP 바인딩 요소의 목적은 바인딩이 SOAP 프로토콜 서식에 바운드된다는 것을 나타내는 것입니다. 이 요소는 메시지의 인코딩 및 서식에 요청을 만들지 않습니다(예: SOAP 1.1 규격의 5절을 따르는 메시지).

soap:binding 요소는 SOAP 바인딩을 사용할 때 반드시 표시되어야 합니다.

<definitions…>
<binding…>
<soap:binding transport="uri"? style="rpc|document"?>
</binding>
</definitions>

style 특성의 값은 포함된 각 작업에 대한 style 특성의 기본값입니다. style 특성이 생략된 경우 "document"로 간주됩니다. style의 기능에 대한 정보는 3.4절을 참조하십시오.

요청된 transport 특성의 값은 이 바인딩이 SOAP의 어느 전송에 해당하는지를 나타냅니다. URI 값 http://schemas.xmlsoap.org/soap/http는 SOAP 규격에서 HTTP 바인딩에 해당합니다. SMTP, FTP 등과 같은 다른 전송을 나타내기 위해 여기에 다른 URI가 사용되기도 합니다.

맨 위로


3.4 soap:operation

soap:operation 요소는 작업에 대한 전반적인 정보를 제공합니다.

<definitions…>
<binding…>
<operation…>
<soap:operation soapAction="uri"? style="rpc|document"?>
</operation>
</binding>
</definitions>

style 특성은 작업이 매개 변수 및 반환값을 포함하는 RPC 지향적인 메시지인지 문서를 포함하는 문서 지향적인 메시지인지를 나타냅니다. 이 정보는 적합한 프로그래밍 모델을 선택하는 데 사용됩니다. 특성이 지정되지 않은 경우 soap:binding 요소에 지정된 값이 기본값이 됩니다. soap:binding 요소가 스타일을 지정하지 않은 경우에는 "document"로 간주됩니다.

soapAction 특성은 이 작업에 대한 SOAPAction 헤더의 값을 지정합니다. 이 URI 값은 SOAPAction 헤더에 대한 값으로 직접 사용되어야 하며 요청 시 상대적인 URI 값을 절대값으로 만들 수 없습니다. SOAP의 HTTP 프로토콜 바인딩인 경우에는 이 값이 필요하며 기본값이 없습니다. 다른 SOAP 프로토콜 바인딩의 경우 이 값은 지정되지 않을 수도 있고 soap:operation 요소가 생략될 수도 있습니다.

맨 위로


3.5 soap:body

soap:body 요소는 SOAP Body 요소에서 메시지 부분이 나타나는 방법을 지정합니다.

메시지의 부분은 추상적인 형식 정의 또는 구체적인 스키마 정의가 될 수 있습니다. 추상 정의인 경우, 인코딩 스타일에 의해 정의된 일부 규칙 집합에 따라 형식에 순서가 정해집니다. 각 인코딩 스타일은 SOAP 규격에 정의된 바와 같이 URI 목록을 사용하여 식별됩니다. SOAP 인코딩(http://schemas.xmlsoap.org/soap/encoding/)과 같은 일부 인코딩 스타일은 지정된 추상적인 형식 집합에 대한 메시지 형식의 변형을 허용하기 때문에, 모든 변형된 형식을 이해하는 것은 메시지를 읽는 사람의 몫입니다. 즉, 읽는쪽이 올바르게 읽어야 합니다. 모든 변형을 지원할 필요가 없도록 하려면 메시지가 구체적으로 정의된 다음, 참고로서 원래 인코딩 스타일(있는 경우)임을 나타내야 합니다. 이 경우 메시지 작성자는 지정된 스키마를 정확하게 준수해야 합니다. 즉, 쓰는쪽이 올바르게 써야 합니다.

soap:body 바인딩 요소는 SOAP 메시지의 Body 요소 내에 있는 메시지 부분을 조합하는 방법에 대한 정보를 제공합니다. soap:body 요소는 RPC 지향적 메시지와 문서 지향적 메시지에 사용되지만 enclosing 작업의 스타일은 Body 구역을 구성하는 방법에 중요한 영향을 미칩니다.

  • 작업 스타일이 rpc인 경우 각 부분은 매개 변수 또는 반환 값이며 body에 있는 wrapper 요소에 나타납니다(SOAP 규격의 7.1절 참조). wrapper 요소는 작업 이름과 동일한 이름을 가지며 이름 공간은 이름 공간 속성의 값입니다. 각 메시지 부분(매개 변수)은 래퍼 아래 나타나며 호출에 대응하는 매개 변수와 동일한 이름의 accessor로 표현됩니다. 여기서 각 부분은 호출의 매개 변수와 같은 순서로 배열됩니다.
  • 작업 스타일이 문서인 경우 추가 래퍼는 없으며 메시지 부분은 SOAP Body 요소 바로 아래 나타납니다.

Body와 매개 변수 accessor 요소의 컨텐트를 정의하는 데 동일한 메커니즘을 사용합니다.

<definitions…>
<binding…>
<operation…>
<input>
<soap:body parts="nmtokens"? use="literal|encoded"?
encodingStyle="uri-list"? namespace="uri"?>
</input>
<output>
<soap:body parts="nmtokens"? use="literal|encoded"?
encodingStyle="uri-list"? namespace="uri"?>
</output>
</operation>
</binding>
</definitions>

nmtokens 형식의 선택적인 parts 특성은 어느 부분이 메시지의 SOAP Body 내에서 어디에 나타나는지를 표시합니다. 메시지의 다른 부분은 SOAP가 multipart/related MIME 바인딩과 함께 사용될 때와 같이 다른 메시지 영역에 나타날 수 있습니다. parts 특성이 생략되면 메시지에서 정의한 모든 부분이 SOAP Body 영역에 포함된 것으로 간주됩니다.

요청된 use 특성은 몇몇 인코딩 규칙을 사용하여 메시지 부분이 인코드되는지의 여부 또는 부분이 메시지의 구체적인 스키마를 정의했는지의 여부를 나타냅니다.

use가 encoded인 경우에는 각 메시지 부분은 type 특성을 사용하여 추상적인 형식을 참조합니다. 이러한 추상적인 형식은 encodingStyle 특성으로 지정된 인코딩을 적용하여 구체적인 메시지를 작성하는 데 사용됩니다. namespace 특성이 추상적인 형식에 의해 명시적으로 정의되지 않은 컨텐트에만 적용되는 경우에도, names, types 부분 및 namespace 특성의 값은 모두 인코딩의 입력이 됩니다. 참조된 인코딩 스타일이 SOAP 인코딩과 마찬가지로 인코딩 스타일의 변형을 허용하면 모든 변형이 지원되어야 합니다. 즉, 읽는쪽이 올바르게 읽어야 합니다.

use가 literal인 경우에 각 부분은 간단한 부분에 대해서는 element 특성을 사용하거나 복잡한 부분에 대해서는 type 특성을 사용해서 구체적인 스키마를 참조합니다(2.3.1절 참고). encodingStyle 특성의 값은 구체적인 서식이 SOAP 인코딩과 같은 특정 인코딩을 사용하여 파생된 것이지만 지정된 변형만 지원한다는 것을 나타냅니다. 즉, 쓰는쪽이 올바르게 써야 합니다.

encodingStyle 특성의 값은 각각이 단일 공백으로 분리된 URI 목록입니다. URI는 메시지 내에서 사용되는 인코딩을 제한 사항이 가장 많은 것에서 가장 적은 것의 순서로 표시합니다(SOAP 규격에 정의된 encodingStyle 특성과 동일함).

맨 위로


3.6 soap:fault

soap:fault 요소는 SOAP Fault Details 요소의 컨텐트를 지정합니다. 이 요소는 soap:body 요소 뒤에 패턴화됩니다(3.5절 참조).

<definitions…>
<binding…>
<operation…>
<fault>*
<soap:fault name="nmtoken" use="literal|encoded"
encodingStyle="uri-list"? namespace="uri"?>

</fault>
</operation>
</binding>
</definitions>

name 특성은 soap:fault를 작업에 대해 정의된 wsdl:fault에 연결합니다.

fault 메시지는 단일 부분을 가져야 합니다. use, encodingStylenamespace 특성은 모두 soap:body와 동일한 방법으로 사용됩니다(3.5절 참조).

맨 위로


3.7 soap:header

soap:header 요소는 header가 SOAP Envelope의 Header 요소 내에서 전송되도록 정의할 수 있습니다. 이 구역에 모든 헤더를 나열할 필요는 없습니다. WSDL 문서의 다른 규격에 의해 헤더가 실제 페이로드에 추가되도록 하는 것이 일반적이기 때문에 여기에 모든 헤더를 나열할 필요가 없습니다.

<definitions .... >
<binding .... >
<operation .... >
<input>
<soap:body parts="nmtokens"? use="literal|encoded"?
encodingStyle="uri-list"? namespace="uri"?>
</input>
<output>
<soap:body parts="nmtokens"? use="literal|encoded"?
encodingStyle="uri-list"? namespace="uri"?>
</output>
</operation>
</binding>
</definitions>

use, encodingStylenamespace 특성은 모두 soap:body(3.5절 참조)와 같은 방식으로 사용되며 헤더에 매개 변수가 포함되지 않기 때문에 only style="document"인 것으로 가정합니다

Qname 형식의 message 특성과 nmtoken 형식의 part 특성은 헤더 형식을 정의하는 메시지 부분을 참조합니다. 부분 MAY가 참조하는 스키마는 use="literal"일 경우 soap:actor와 soap:mustUnderstand 특성의 정의를 포함하지만 use="encoded"일 경우에는 포함해서는 안됩니다. 참조된 메시지는 SOAP Body를 정의하는 메시지와 같지 않아도 됩니다.

soap:header 내에 나타나고 soap:header와 같은 구문을 갖는 선택적인 headerfault 요소를 사용하면 soap:header에서 정의하는 헤더에 속하는 오류 정보를 전송하는 데 사용된 헤더 형식 규격이 허용됩니다. SOAP 규격은 헤더에 속하는 오류가 헤더로 반환되어야 한다고 규정하며 이러한 메커니즘을 사용하면 이와 같은 헤더 형식 규격이 허용됩니다.

맨 위로


3.8 soap:address

SOAP 주소 바인딩은 포트에 주소(URI)를 지정하는 데 사용됩니다. SOAP 바인딩을 사용하는 포트는 반드시 하나의 주소만 지정해야 합니다.

<definitions…>
<port…>
<binding…>
<soap:address location="uri"/>
</binding>
</port>
</definitions>

맨 위로


4. HTTP GET 및 POST 바인딩

WSDL은 웹 브라우저와 웹 사이트 간의 상호 작용을 설명하기 위해 HTTP 1.1의 GET 및 POST 동사에 대한 바인딩을 포함합니다. 이 기능은 웹 브라우저가 아닌 응용 프로그램이 사이트와 상호 작용하도록 합니다. 다음과 같은 프로토콜별 정보를 지정할 수 있습니다.

  • HTTP GET 또는 POST를 사용하는 바인딩 표시
  • 포트에 대한 주소
  • 각 작업에 대한 상대 주소(포트에서 정의한 기본 주소에 상대적임)

맨 위로


4.1 HTTP GET/POST 예제

다음 예제는 지정된 포트 형식에 대해 다르게 바운드된 세 개의 포트를 보여 줍니다.

전달된 값이 part1=1, part2=2, part3=3인 경우, 각 포트에 대한 요청 형식은 다음과 같습니다.

port1: GET, URL="http://example.com/o1/A1B2/3"
port2: GET, URL="http://example.com/o1?p1=1&p2=2&p3=3
port3: POST, URL="http://example.com/o1", PAYLOAD="p1=1&p2=2&p3=3"

각 포트에 대한 응답은 GIF 또는 JPEG 이미지가 됩니다.

예제 5. GIF 또는 JPG를 반환하는 GET 및 FORM POST


<definitions…>
<message name="m1">
<part name="part1" type="xsd:string"/>
<part name="part2" type="xsd:int"/>
<part name="part3" type="xsd:string"/>
</message>

<message name="m2">
<part name="image" type="xsd:binary"/>
</message>

<portType name="pt1">
<operation name="o1">
<input message="tns:m1"/>
<output message="tns:m2"/>
</operation>
</portType>

<service name="service1">
<port name="port1" binding="tns:b1">
<http:address location="http://example.com/"/>
</port>
<port name="port2" binding="tns:b1">
<http:address location="http://example.com/"/>
</port>
<port name="port3" binding="tns:b1">
<http:address location="http://example.com/"/>
</port>
</service>

<binding name="b1" type="pt1">
<http:binding verb="GET"/>
<operation name="o1">
<http:operation location="o1/A(part1)B(part2)/(part3)"/>
<input>
<http:urlReplacement/>
</input>
<output>
<mime:content type="image/gif"/>
<mime:content type="image/jpeg"/>
</output>
</operation>
</binding>

<binding name="b2" type="pt1">
<http:binding verb="GET"/>
<operation name="o1">
<http:operation location="o1"/>
<input>
<http:urlEncoded/>
</input>

<output>
<mime:content type="image/gif"/>
<mime:content type="image/jpeg"/>

</output>
</operation>
</binding>

<binding name="b3" type="pt1">
<http:binding verb="POST"/>
<operation name="o1">
<http:operation location="o1"/>
<input>
<mime:content type="application/x-www-form-urlencoded"/>
</input>
<output>
<mime:content type="image/gif"/>
<mime:content type="image/jpeg"/>

</output>
</operation>
</binding>
</definitions>

맨 위로


4.2 HTTP GET/POST 바인딩이 WSDL을 확장하는 방법

HTTP GET/POST 바인딩은 다음과 같은 확장 요소를 사용하여 WSDL을 확장합니다.

<definitions…>
<binding…>
<http:binding verb="nmtoken"/>
<operation…>
<http:operation location="uri"/>
<input…>
<-- mime elements -->
</input>
<output…>
<-- mime elements -->
</output>
</operation>
</binding>

<port…>
<http:address location="uri"/>
</port>
</definitions>

이러한 요소는 다음 절에 설명되어 있습니다.

맨 위로


4.3 http:address

location 특성은 포트에 대해 기본 URI를 지정합니다. 이 특성의 값은 http:operation 바인딩 요소의 location 특성의 값과 결합됩니다. 자세한 내용은 4.5절을 참조하십시오.

맨 위로


4.4 http:binding

http:binding 요소는 이 바인딩이 HTTP 프로토콜을 사용한다는 것을 나타냅니다.

<definitions…>
<binding…>
<http:binding verb="nmtoken"/>
</binding>
</definitions>

요청된 verb 특성의 값은 HTTP 동사를 나타냅니다. 일반적인 값은 GET 또는 POST이지만 다른 값이 사용될 수도 있습니다. HTTP 동사는 대소문자를 구별해야 합니다.

맨 위로


4.5 http:operation

location 특성은 작업에 대해 상대 URI를 지정합니다. 이 URI는 http:address 요소에 지정된 URI와 결합하여 HTTP 요청에 대한 전체 URI를 만듭니다. URI 값은 상대 URI여야 합니다.

<definitions…>
<binding…>
<operation…>
<http:operation location="uri"/>
</operation>
</binding>
</definitions>

맨 위로


4.6 http:urlEncoded

urlEncoded 요소는 메시지의 모든 부분이 표준 URI 인코딩 규칙(name1=value&name2=value…)을 사용하는 HTTP 요청 URI에 인코드된다는 것을 나타냅니다. 매개 변수의 이름은 메시지 부분의 이름에 해당합니다. 부분에서 제공한 각 값은 이름=값 쌍을 사용하여 인코드됩니다. 이 값은 GET과 함께 사용되어 URL 인코딩을 지정하거나 POST와 함께 사용되어 FORM-POST를 지정하기도 합니다. GET과 함께 사용될 경우 "?" 문자는 필요할 때 자동으로 추가됩니다.

<http:urlEncoded/>

URI 인코딩 매개 변수의 규칙에 대한 자세한 내용은 [5], [6] 및 [7]을 참조하십시오.

맨 위로


4.7 http:urlReplacement

http:urlReplacment 요소는 메시지의 모든 부분이 배치 알고리즘을 사용하는 HTTP 요청 URI로 인코드된다는 것을 나타냅니다.

  • http:operation의 상대 URI 값을 검색하여 검색 패턴 집합을 찾습니다.
  • http:operation의 값이 http:address의 location 특성 값과 결합되기 전에 검색이 수행됩니다.
  • 메시지 부분마다 하나의 검색 패턴이 있습니다. 검색 패턴 문자열은 괄호"(" 및 ")"로 둘러 쌓인 메시지 부분의 이름입니다.
  • 일치하는 경우 해당 메시지 부분의 값은 일치된 위치에 있는 내용으로 대치됩니다.
  • 일치 항목을 찾은 후에 값이 바뀌며 바뀐 값은 추가적인 검색 작업을 수행하지 않습니다.

메시지 부분에는 반복되는 값이 없을 수도 있습니다.

<http:urlReplacement/>

맨 위로


5. MIME 바인딩

WSDL은 추상적인 형식을 특정 MIME 형식으로 된 구체적인 메시지에 바인드하는 방법을 가지고 있으며 다음과 같은 MIME 형식에 대한 바인딩이 정의되어 있습니다.

  • multipart/related
  • text/xml
  • application/x-www-form-urlencoded (HTML로 된 폼을 전송하는 데 사용하는 형식)
  • 기타(MIME 형식 문자열 지정)

정의된 MIME 형식의 집합은 계속적으로 크기가 증가하기 때문에, 각 MIME 형식에 대해 XML 문법을 철저하게 정의하는 것이 WSDL의 목표는 아닙니다. 필요한 경우 언제든지 추가적인 MIME 형식에 대한 추가 문법을 정의할 수 있습니다. 컨텐트를 설명하는 데 MIME 형식 문자열을 사용할 수 있다면 아래 정의된 mime 요소를 사용할 수 있습니다.

맨 위로


5.1 MIME 바인딩 예제

예제 7. SOAP에 multipart/related 사용

이 예제는 SOAP 1.1 HTTP 바인딩을 통해 GetCompanyInfo SOAP 1.1 요청을 StockQuote 서비스로 보내는 내용을 설명합니다. 요청은 문자열 형식의 증권 시세 표시기 기호를 입력으로 받습니다. 응답에는 MIME 형식 multipart/related로 인코드된 여러 개의 부분이 포함되어 있습니다. 즉, 부동 소수점으로 된 현재 증권 시세 가격이 있는 SOAP Envelope, HTML 형식으로 된 제로 또는 그 이상의 마케팅 자료 및 GIF 또는 JPFG 형식으로 된 선택적인 회사 로고 등이 여기에 해당합니다.

<definitions…>

<types>
<schema…>
<element name="GetCompanyInfo">
<complexType>
<all>
<element name="tickerSymbol " type="string"/>
</all>
</complexType>
</element>
<element name="GetCompanyInfoResult">
<complexType>
<all>
<element name="result" type="float"/>
</all>
</complexType>
</element>
<complexType name="ArrayOfBinary" base="soap:Array">
<all>
<element name="value" type="xsd:binary"/>
</all>
</complexType>
</schema>
</types>

<message name="m1">
<part name="body" element="tns:GetCompanyInfo"/>
</message>

<message name="m2">
<part name="body" element="tns:GetCompanyInfoResult"/>
<part name="docs" type="xsd:string"/>
<part name="logo" type="tns:ArrayOfBinary"/>
</message>

<portType name="pt1">
<operation name="GetCompanyInfo">
<input message="m1"/>
<output message="m2"/>
</operation>
</portType>

<binding name="b1" type="tns:pt1">
<operation name="GetCompanyInfo">
<soap:operation soapAction="http://example.com/GetCompanyInfo"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<mime:multipartRelated>
<mime:part>
<soap:body parts="body" use="literal"/>
</mime:part>
<mime:part>
<mime:content part="docs" type="text/html"/>
</mime:part>
<mime:part>
<mime:content part="logo" type="image/gif"/>
<mime:content part="logo" type="image/jpeg"/>
</mime:part>
</mime:multipartRelated>
</output>
</operation>
</binding>

<service name="CompanyInfoService">
<port name="CompanyInfoPort"binding="tns:b1">
<soap:address location="http://example.com/companyinfo"/>
</port>
</service>
</definitions>

맨 위로


5.2 MIME 바인딩이 WSDL을 확장하는 방법

MIME 바인딩은 다음과 같은 확장 요소를 사용하여 WSDL을 확장합니다.

<mime:content part="nmtoken"? type="string"?/>

<mime:multipartRelated>
<mime:part> *
<-- mime element -->
</mime:part>
</mime:multipartRelated>

<mime:mimeXml part="nmtoken"?/>

이러한 요소는 다음과 같은 WSDL의 위치에서 사용됩니다.

<definitions…>
<binding…>
<operation…>
<input…>
<-- mime elements -->
</input>
<output…>
<-- mime elements -->
</output>
</operation>
</binding>
</definitions>

MIME 요소는 input 및 output 아래 나타나 MIME 형식을 지정합니다. 여러 개의 MIME 요소가 나타나는 경우 이를 대체 요소로 간주합니다.

맨 위로


5.3 mime:content

모든 MIME 형식에 대해 새 요소를 정의할 필요가 없도록 하기 위해, MIME 형식 문자열 외에 전달할 추가 정보가 없는 경우 mime:content 요소를 사용할 수 있습니다.

<mime:content part="nmtoken"? type="string"?/>

part 특성은 메시지 부분의 이름을 지정하는 데 사용됩니다. 메시지가 단일 부분을 가지고 있는 경우에는 부분의 특성은 선택적입니다. type 특성은 MIME 형식 문자열을 포함합니다. 형식의 값은 슬래시(/) 또는 와일드카드(*)로 구분된 두 영역이 있습니다. type 특성을 지정하지 않으면 모든 MIME 형식을 허용한다는 것을 나타냅니다.

반환 형식이 XML인데 스키마가 미리 알려지지 않은 경우, text/xml을 표시하는 일반적인 mime 요소를 사용할 수 있습니다.

<mime:content type="text/xml"/>

와일드카드(*)는 모든 텍스트 형식과 같이 mime 형식의 패밀리를 지정하는 데 사용됩니다.

<mime:content type="text/*"/>

다음 두 예제는 모든 mime 형식을 지정합니다.

<mime:content type="*/*"/>
<mime:content/>

맨 위로


5.4 mime:multipartRelated

multipart/related MIME 형식은 MIME 형식으로 된 부분의 임의 집합을 MIME 형식 "multipart/related"를 사용하는 하나의 메시지에 집계합니다. mime:multipartRelated 요소는 이런 메시지의 구체적인 형식을 나타냅니다.

<mime:multipartRelated>
<mime:part> *
<-- mime element -->
</mime:part>
</mime:multipartRelated>

mime:part 요소는 multipart/related 메시지의 각 부분을 설명합니다. MIME 요소는 mime:part에 나타나며 해당 부분에 대한 구체적인 MIME 형식을 지정합니다. mime:part 내에 둘 이상의 MIME 요소가 나타나면 이들은 대체 요소입니다.

5.5 soap:body

SOAP 요청과 함께 MIME 바인딩을 사용할 때, MIME 요소로 soap:body 요소를 사용할 수 있습니다. 이것은 컨텐트 형식이 "text/xml"이고, 이를 포함하는 SOAP Envelope가 있음을 나타냅니다.

5.6 mime:mimeXml

SOAP 규격이 아니면서(SOAP Envelope가 없음) 특정 스키마를 가지고 있는 XML 페이로드를 지정하기 위해, mime:mimeXml 요소를 사용하여 구체적인 스키마를 지정할 수 있습니다. part 특성은 루트 XML 요소의 구체적인 스키마를 정의하는 메시지 부분을 참조합니다. part 특성은 메시지가 단일 부분을 가지고 있는 경우에는 생략될 수도 있습니다. 해당 부분은 간단한 부분에 대해서는 element 특성을 사용하고 복잡한 부분에 대해서는 type 특성을 사용하여 구체적인 스키마를 참조합니다(2.3.1절 참조).

<mime:mimeXml part="nmtoken"?/>

맨 위로


6. 참조

[2] S. Bradner, "RFC에서 요청 수준을 표시하는 키워드 사용법", RFC 2119 , Harvard University, 1997년 3월

[4] T. Berners-Lee, R. Fielding, L. Masinter, "Uniform Resource Identifiers (URI): 일반 구문", RFC 2396 , MIT/LCS, U.C. Irvine, Xerox Corporation, 1998년 8월.

[5] http://www.w3.org/TR/html401/interact/forms.html - submit-format 

[6] http://www.w3.org/TR/html401/appendix/notes.html - ampersands-in-uris 

[7] http://www.w3.org/TR/html401/interact/forms.html - h-17.13.4 

[8] Simple Object Access Protocol (SOAP) 1.1 "http://www.w3.org/TR/2000/NOTE-SOAP-20000508/

[10] W3C Working Draft "XML 스키마 1부: 구조 ". 현재 처리 중입니다.

[11] W3C Working Draft "XML 스키마 2부: 데이터형식 ". 현재 처리 중입니다.

맨 위로


A 1. URI에 대한 참고

이 절에서는 해당 규격에 직접적인 관련은 없지만 규격을 구현할 때 유용한 배경 정보를 제공합니다.

A 1.1 XML 이름 공간 및 스키마 위치

XML 스키마의 targetNamespace 또는 XML 인스턴스의 xmlns 특성을 해당 스키마의 위치로 잘못 인식하는 경우가 많습니다. 이름 공간은 사실 URI이고 이 URI는 위치를 나타낼 수 있으며 해당 위치에서 스키마를 검색할 수 있기는 하지만 이 스키마만 이름 공간과 연관된 것은 아닙니다. 특정 이름 공간과 연관된 여러 개의 스키마가 있을 수 있고, 특정 처리 컨텍스트에서 어떤 스키마를 사용할지는 XML의 프로세서가 결정합니다. 여기서 WSDL 규격은 유사한 개념의 XML 스키마를 기반으로 하는 <import> 메커니즘을 통해 처리 컨텍스트를 제공합니다.

맨 위로


A 1.2 상대 URI

이 문서를 통해 WSDL 및 XSD 문서에서 정식 URI를 볼 수 있습니다. 정식 URI의 사용은 단순히 참조하는 개념을 보여주는 것입니다. 상대 URI의 사용은 전적으로 허용되며 많은 경우에 그 사용이 보장됩니다. 상대 URI 처리에 관한 내용은 http://www.normos.org/ietf/rfc/rfc2396.txt 를 참조하십시오.

A 1.3 URI 작성

WSDL로 작업할 때 항상 전역적으로 고유한 URI를 작성하는 대신 특정 엔티티에 대한 URI를 작성하여 해당 엔티티 버전(스키마, WSDL 문서 등)을 "의미"하도록 하는 것이 바람직한 경우가 있습니다. 이러한 유형의 동작에 사용하기 위해 예약된 특별한 기본 URI가 있습니다. 기본 URI인 http://tempuri.org/는 어떤 엔티티와도 고유한 연관성이 없는 URI를 구성하는 데 사용될 수 있습니다. 예를 들어, 두 사람 또는 두개의 프로그램에서 완전히 다른 두 스키마에 대해 URI인 http://tempuri.org/myschema를 동시에 사용할 수 있고 URI 사용의 범위가 교차하지 않으면 고유한 URI로 간주됩니다. 이러한 기능은 URI에 의해 참조된 엔티티가 처리 중인 컨텍스트 내에서 유효하기만 하다면 새로운 URI를 작성하지 않고도 설명될 수 있다는 장점이 있습니다. 안정적이고 고정된 엔티티에 대해, http://tempuri.org/를 기본 URI로 사용하는 것은 바람직하지 못합니다.

A 2. 네트워크 형식의 WSDL 예제

A 2.1. 예제 1

HTTP 요청에 포함된 SOAP 메시지

POST /StockQuote HTTP/1.1
Host: www.stockquoteserver.com
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn
SOAPAction: "Some-URI"

<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<m:GetLastTradePrice xmlns:m="Some-URI">
<symbol>DIS</symbol>
</m:GetLastTradePrice>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

HTTP 응답에 포함된 SOAP 메시지

HTTP/1.1 200 OK
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn

<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
<SOAP-ENV:Body>
<m:GetLastTradePriceResponse xmlns:m="Some-URI">
<Price>34.5</Price>
</m:GetLastTradePriceResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

맨 위로


A 3. 확장성 요소의 위치

확장성 요소는 WSDL 문서의 다음과 같은 위치에서 나타날 수 있습니다.

위치 의미 사용법
definitions 확장성 요소는 WSDL 문서에 전반적으로 적용됩니다. · WSDL 문서에 추가 정보 또는 정의를 전반적으로 소개합니다.
definitions/types 확장성 요소는 형식 시스템입니다. · XSD가 아닌 형식 시스템에 메시지의 서식을 지정합니다.
definitions/service 확장성 요소는 service에 적용됩니다. · service에 추가 정보 또는 정의를 소개합니다.
definitions/service/port 확장성 요소는 port에 적용됩니다. · port에 address를 지정합니다.
definitions/binding 확장성 요소는 binding에 전반적으로 적용됩니다. · 모든 작업에 적용할 프로토콜별 정보를 바운드 될 port 형식에 제공합니다.
definitions/binding/operation 확장성 요소는 operation에 전반적으로 적용됩니다. · input 및 output 메시지에 적용할 프로토콜별 정보를 제공합니다.
definitions/binding/operation/input 확장성 요소는 operation에 대한 input 메시지를 적용합니다. · 추상 메시지 부분이 바인딩 데이터 형식 및 구체적인 프로토콜에 매핑되는 방법에 대한 자세한 정보를 제공합니다.

· input 메시지에 추가적인 프로토콜별 정보를 제공합니다.

definitions/binding/operation/output 확장성 요소는 operation에 대한 output 메시지에 적용됩니다. · 추상 메시지 부분이 바인딩 데이터 형식 및 구체적인 프로토콜에 매핑되는 방법에 대한 자세한 정보를 제공합니다.

· output 메시지에 추가 프로토콜별 정보를 제공합니다.

definitions/binding/operation/fault 확장성 요소는 operation의 fault 메시지에 적용됩니다. · 추상 메시지 부분이 바인딩 데이터 형식 및 구체적인 프로토콜에 매핑되는 방법에 대한 자세한 정보를 제공합니다.

· fault 메시지에 추가적인 프로토콜별 정보를 제공합니다.


맨 위로


A 4. 스키마

A 4.1 WSDL 스키마

<schema xmlns="http://www.w3.org/2000/10/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="http://schemas.xmlsoap.org/wsdl/"
elementFormDefault="qualified">
<element name="documentation">
<complexType mixed="true">
<choice minOccurs="0" maxOccurs="unbounded">
<any minOccurs="0" maxOccurs="unbounded"/>
</choice>
<anyAttribute/>
</complexType>
</element>
<complexType name="documented" abstract="true">
<sequence>
<element ref="wsdl:documentation" minOccurs="0"/>
</sequence>
</complexType>
<complexType name="openAtts" abstract="true">
<annotation>
<documentation>
This type is extended by component types
to allow attributes from other namespaces to be added.
</documentation>
</annotation>
<sequence>
<element ref="wsdl:documentation" minOccurs="0"/>
</sequence>
<anyAttribute namespace="##other"/>
</complexType>
<element name="definitions" type="wsdl:definitionsType">
<key name="message">
<selector xpath="message"/>
<field xpath="@name"/>
</key>
<key name="portType">
<selector xpath="portType"/>
<field xpath="@name"/>
</key>
<key name="binding">
<selector xpath="binding"/>
<field xpath="@name"/>
</key>
<key name="service">
<selector xpath="service"/>
<field xpath="@name"/>
</key>
<key name="import">
<selector xpath="import"/>
<field xpath="@namespace"/>
</key>
<key name="port">
<selector xpath="service/port"/>
<field xpath="@name"/>
</key>
</element>
<complexType name="definitionsType">
<complexContent>
<extension base="wsdl:documented">
<sequence>
<element ref="wsdl:import" minOccurs="0" maxOccurs="unbounded"/>
<element ref="wsdl:types" minOccurs="0"/>
<element ref="wsdl:message" minOccurs="0" maxOccurs="unbounded"/>
<element ref="wsdl:portType" minOccurs="0" maxOccurs="unbounded"/>
<element ref="wsdl:binding" minOccurs="0" maxOccurs="unbounded"/>
<element ref="wsdl:service" minOccurs="0" maxOccurs="unbounded"/>
<any namespace="##other" minOccurs="0" maxOccurs="unbounded">
<annotation>
<documentation>to support extensibility elements </documentation>
</annotation>
</any>
</sequence>
<attribute name="targetNamespace" type="uriReference" use="optional"/>
<attribute name="name" type="NMTOKEN" use="optional"/>
</extension>
</complexContent>
</complexType>
<element name="import" type="wsdl:importType"/>
<complexType name="importType">
<complexContent>
<extension base="wsdl:documented">
<attribute name="namespace" type="uriReference" use="required"/>
<attribute name="location" type="uriReference" use="required"/>
</extension>
</complexContent>
</complexType>
<element name="types" type="wsdl:typesType"/>
<complexType name="typesType">
<complexContent>
<extension base="wsdl:documented">
<sequence>
<any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</extension>
</complexContent>
</complexType>
<element name="message" type="wsdl:messageType">
<unique name="part">
<selector xpath="part"/>
<field xpath="@name"/>
</unique>
</element>
<complexType name="messageType">
<complexContent>
<extension base="wsdl:documented">
<sequence>
<element ref="wsdl:part" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
<attribute name="name" type="NCName" use="required"/>
</extension>
</complexContent>
</complexType>
<element name="part" type="wsdl:partType"/>
<complexType name="partType">
<complexContent>
<extension base="wsdl:openAtts">
<attribute name="name" type="NMTOKEN" use="optional"/>
<attribute name="type" type="QName" use="optional"/>
<attribute name="element" type="QName" use="optional"/>
</extension>
</complexContent>
</complexType>
<element name="portType" type="wsdl:portTypeType"/>
<complexType name="portTypeType">
<complexContent>
<extension base="wsdl:documented">
<sequence>
<element ref="wsdl:operation" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
<attribute name="name" type="NCName" use="required"/>
</extension>
</complexContent>
</complexType>
<element name="operation" type="wsdl:operationType"/>
<complexType name="operationType">
<complexContent>
<extension base="wsdl:documented">
<choice>
<group ref="wsdl:one-way-operation"/>
<group ref="wsdl:request-response-operation"/>
<group ref="wsdl:solicit-response-operation"/>
<group ref="wsdl:notification-operation"/>
</choice>
<attribute name="name" type="NCName" use="required"/>
</extension>
</complexContent>
</complexType>
<group name="one-way-operation">
<sequence>
<element ref="wsdl:input"/>
</sequence>
</group>
<group name="request-response-operation">
<sequence>
<element ref="wsdl:input"/>
<element ref="wsdl:output"/>
<element ref="wsdl:fault" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</group>
<group name="solicit-response-operation">
<sequence>
<element ref="wsdl:output"/>
<element ref="wsdl:input"/>
<element ref="wsdl:fault" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</group>
<group name="notification-operation">
<sequence>
<element ref="wsdl:output"/>
</sequence>
</group>
<element name="input" type="wsdl:paramType"/>
<element name="output" type="wsdl:paramType"/>
<element name="fault" type="wsdl:faultType"/>
<complexType name="paramType">
<complexContent>
<extension base="wsdl:documented">
<attribute name="name" type="NMTOKEN" use="optional"/>
<attribute name="message" type="QName" use="required"/>
</extension>
</complexContent>
</complexType>
<complexType name="faultType">
<complexContent>
<extension base="wsdl:documented">
<attribute name="name" type="NMTOKEN" use="required"/>
<attribute name="message" type="QName" use="required"/>
</extension>
</complexContent>
</complexType>
<complexType name="startWithExtensionsType" abstract="true">
<complexContent>
<extension base="wsdl:documented">
<sequence>
<any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</extension>
</complexContent>
</complexType>
<element name="binding" type="wsdl:bindingType"/>
<complexType name="bindingType">
<complexContent>
<extension base="wsdl:startWithExtensionsType">
<sequence>
<element name="operation" type="wsdl:binding_operationType" minOccurs="0"
maxOccurs="unbounded"/>
</sequence>
<attribute name="name" type="NCName" use="required"/>
<attribute name="type" type="QName" use="required"/>
</extension>
</complexContent>
</complexType>
<complexType name="binding_operationType">
<complexContent>
<extension base="wsdl:startWithExtensionsType">
<sequence>
<element name="input" type="wsdl:startWithExtensionsType" minOccurs="0"/>
<element name="output" type="wsdl:startWithExtensionsType" minOccurs="0"/>
<element name="fault" minOccurs="0" maxOccurs="unbounded">
<complexType>
<complexContent>
<extension base="wsdl:startWithExtensionsType">
<attribute name="name" type="NMTOKEN" use="required"/>
</extension>
</complexContent>
</complexType>
</element>
</sequence>
<attribute name="name" type="NCName" use="required"/>
</extension>
</complexContent>
</complexType>
<element name="service" type="wsdl:serviceType"/>
<complexType name="serviceType">
<complexContent>
<extension base="wsdl:documented">
<sequence>
<element ref="wsdl:port" minOccurs="0" maxOccurs="unbounded"/>
<any namespace="##other" minOccurs="0"/>
</sequence>
<attribute name="name" type="NCName" use="required"/>
</extension>
</complexContent>
</complexType>
<element name="port" type="wsdl:portType"/>
<complexType name="portType">
<complexContent>
<extension base="wsdl:documented">
<sequence>
<any namespace="##other" minOccurs="0"/>
</sequence>
<attribute name="name" type="NCName" use="required"/>
<attribute name="binding" type="QName" use="required"/>
</extension>
</complexContent>
</complexType>
<attribute name="arrayType" type="string"/>
</schema>

맨 위로


A 4.2 SOAP 바인딩 스키마

<schema xmlns="http://www.w3.org/2000/10/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
targetNamespace="http://schemas.xmlsoap.org/wsdl/soap/">
<element name="binding" type="soap:bindingType"/>
<complexType name="bindingType">
<attribute name="transport" type="uriReference" use="optional"/>
<attribute name="style" type="soap:styleChoice" use="optional"/>
</complexType>
<simpleType name="styleChoice">
<restriction base="string">
<enumeration value="rpc"/>
<enumeration value="document"/>
</restriction>
</simpleType>
<element name="operation" type="soap:operationType"/>
<complexType name="operationType">
<attribute name="soapAction" type="uriReference" use="optional"/>
<attribute name="style" type="soap:styleChoice" use="optional"/>
</complexType>
<element name="body" type="soap:bodyType"/>
<complexType name="bodyType">
<attribute name="encodingStyle" type="uriReference" use="optional"/>
<attribute name="parts" type="NMTOKENS" use="optional"/>
<attribute name="use" type="soap:useChoice" use="optional"/>
<attribute name="namespace" type="uriReference" use="optional"/>
</complexType>
<simpleType name="useChoice">
<restriction base="string">
<enumeration value="literal"/>
<enumeration value="encoded"/>
</restriction>
</simpleType>
<element name="fault" type="soap:faultType"/>
<complexType name="faultType">
<complexContent>
<restriction base="soap:bodyType">
<attribute name="parts" type="NMTOKENS" use="prohibited"/>
</restriction>
</complexContent>
</complexType>
<element name="header" type="soap:headerType"/>
<complexType name="headerType">
<all>
<element ref="soap:headerfault">
</all>
<attribute name="message" type="QName" use="required"/>
<attribute name="parts" type="NMTOKENS" use="required"/>
<attribute name="use" type="soap:useChoice" use="required"/>
<attribute name="encodingStyle" type="uriReference" use="optional"/>
<attribute name="namespace" type="uriReference" use="optional"/>
</complexType>
<element name="headerfault" type="soap:headerfaultType"/>
<complexType name="headerfaultType">
<attribute name="message" type="QName" use="required"/>
<attribute name="parts" type="NMTOKENS" use="required"/>
<attribute name="use" type="soap:useChoice" use="required"/>
<attribute name="encodingStyle" type="uriReference" use="optional"/>
<attribute name="namespace" type="uriReference" use="optional"/>
</complexType>
<element name="address" type="soap:addressType"/>
<complexType name="addressType">
<attribute name="location" type="uriReference" use="required"/>
</complexType>
</schema>

맨 위로


A 4.3 HTTP 바인딩 스키마

<schema xmlns="http://www.w3.org/2000/10/XMLSchema"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
targetNamespace="http://schemas.xmlsoap.org/wsdl/http/">
<element name="address" type="http:addressType"/>
<complexType name="addressType">
<attribute name="location" type="uriReference" use="required"/>
</complexType>
<element name="binding" type="http:bindingType"/>
<complexType name="bindingType">
<attribute name="verb" type="NMTOKEN" use="required"/>
</complexType>
<element name="operation" type="http:operationType"/>
<complexType name="operationType">
<attribute name="location" type="uriReference" use="required"/>
</complexType>
<element name="urlEncoded">
<complexType>
</complexType>
</element>
<element name="urlReplacement">
<complexType>
</complexType>
</element>
</schema>

맨 위로


A 4.4 MIME 바인딩 스키마

<schema targetNamespace="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns="http://www.w3.org/2000/10/XMLSchema">
<element name="content" type="mime:contentType"/>
<complexType name="contentType" content="empty">
<attribute name="type" type="string" use="optional"/>
<attribute name="part" type="NMTOKEN" use="optional"/>
</complexType>
<element name="multipartRelated" type="mime:multipartRelatedType"/>
<complexType name="multipartRelatedType" content="elementOnly">
<element ref="mime:part" minOccurs="0" maxOccurs="unbounded"/>
</complexType>
<element name="part" type="mime:partType"/>
<complexType name="partType" content="elementOnly">
<any namespace="targetNamespace" minOccurs="0" maxOccurs="unbounded"/>
<attribute name="name" type="NMTOKEN" use="required"/>
</complexType>
<element name="mimeXml" type="mime:mimeXmlType"/>
<complexType name="mimeXmlType" content="empty">
<attribute name="part" type="NMTOKEN" use="optional"/>
</complexType>
</schema>

'Architecture' 카테고리의 다른 글

티스토리 시스템 장애 관련  (0) 2009.04.17
Map Reduce  (2) 2008.05.14
네트워크 프로그래밍시 유의사항  (0) 2006.07.20
공짜 라이브러리  (0) 2006.01.23
[펌] Dual Core 란 무엇인가?  (0) 2006.01.04
Posted by '김용환'
,
Posted by '김용환'
,

uCOS-ii V2.51을 8051에 포팅하는 포팅기를 적어볼까 합니다.



기존에 포팅경험이 있으신 분들에게는 별 시덥지 않은 포팅기가 될지도 모르지만,

처음 접하시는 분들은 많은 시행착오를 겪어야 하기 때문에,

조금이나마 그 시행착오를 줄이는데 도움이 됐으면 합니다.



uCOS를 포팅하는 방법은 Jean Labrosse님께서 쓰신 uCOS-ii 책에 자세히 설명되어 있으며,

인터넷상에 돌아다니는 문서도 많기 때문에,

포팅의 공통된 부분은 기존 책과 인터넷 자료를 참고하시기 바라며,

저는 8051에 포팅시 주의할 점 위주로 설명할까 합니다.



/********* AT89S52 에 uCOS-ii V2.51 포팅 준비하기. **********/



AT89S52는 ATmel (www.atmel.com) 에서 나온 8051제품입니다.

포팅의 가장 기본은 포팅하고자 하는 MCU에 대해서 이해하는 일이라고 생각하기에

AT89S52의 Features에서 uCOS-ii를 포팅할때 이해해야 할 부분에 대해서만 간단하게 설명하고 넘어가도록 하겠습니다.



AT89S52는 내부에 8Kbyte의 플래쉬 메모리와 256Byte의 내부램을 가지고 있습니다.

내부 플래쉬 메모리는 ISP기능을 지원하므로 사용자가 쉽게 프로그래밍할수 있게 되어 있습니다.



AT89S52는 최대 24MHz 와 33MHz 까지 지원하는 제품으로 나뉘어 있습니다.

24Mhz까지 지원하는 제품은 제품명뒤에 제품코드로 AT89S52 - 24AC 이런식으로 24MHz 지원 제품이라는 코드가 붙습니다.

33Mhz도 마찬가지로 AT89S52 - 33AC 라는 코드가 붙습니다.

이외에도 다른 코드들이 몇가지 더 있으며, ATmel에서 제공하는 AT89S52 데이타 쉬트를 참고하시기 바랍니다.

( 데이타쉬트는 www.atmel.com 에 있습니다.)



내부 플래쉬 메모리와 내부램 , 클럭 이정도만 알면, MCU에서 포팅에 필요한 기초적인 부분은 알았다고 생각되는데요....^^;;

uCOS 의 코드가 들어갈 플래쉬 메모리, uCOS에서 사용할 램, 그리고 uCOS에서 필요한 Tick을 제공할 클럭.

정말 간단하지 않습니까?? ^^



그럼 AT89S52 만으로 uCOS를 포팅할수 있을까?? 하는 부분에 대해서 생각해 봐야겠죠??



참고로 제가 포팅해본 바로는 uCOS가 컴파일 되었을때, 대략 7Kbyte의 코드 사이즈와 1.2kByte 정도의 내부램을 사용합니다.

물론, 옵티마이즈했을 경우에는 달라지겠지만 말입니다.

코드사이즈야 엇비슷하게 나오니...태스크 코드의 양이 많지만 않다면, AT89S52의 내부 플래쉬 메모리를 사용해도 되겠지만...

램의 경우에는 턱없이 부족하게 되죠...^^



그러므로 좀더 넉넉한 코드 메모리와 데이터 메모리를 위해서 외부에 롬과 램을 확장해서 사용해야 하겠습니다.

외부에 롬과 램을 확장하기에 어려운 환경이라면,

ATmel 에서 나온 AT89C51ED2 같은 경우에는 64Kbyte의 플래쉬 메모리와 2K바이트의 내부 램을 지원하므로 이런

디바이스들을 사용하시면 되겠죠??



이제 uCOS를 어떤 컴파일러를 사용해서 컴파일 하느냐가 문제네요...

uCOS는 ANSI C 된 부분과, 약간의 어셈블리어 소스로 구성되어 있습니다.

ANSI C로 된 부분은 8051용 C컴파일러라면 모두 지원하기에 상관이 없지만,

어셈블리어 부분에서는 컴파일러마다 조금씩 다르므로 이부분도 염두에 두셔야 합니다...



8051컴파일러는 여러 종류가 있고... 그중에서 가장 많이 쓰이는 컴파일러는 Keil이라고 생각되는데요....

개인적으로는 Keil이 많은 사람이 쓰기에 인터넷 상에 자료도 많고,

또 www.keil.com 에서 제공해주는 소스 샘플이나,

Q&A도 상당히 풍부하기에 이용하기에는 가장 좋다고 생각합니다.

또 써본바로는 디버깅환경이 실제 환경과 상당히 정확하고, 코드 옵티마이즈 부분또한

타 컴파일러에 비해서 상당히 좋다고 느꼈습니다.



이제 컴파일러와 MCU에 대한 부분이 다 준비가 되었으므로...

uCOS-ii 포팅 소스를 구해오면 포팅 준비는 끝났다고 봅니다...



포팅 소스는 www.uCOS-ii.com 사에트에서 제공되는 8051용 포팅소스를 받으시면 됩니다.

프리 포트 다운로드에 가셔서 Intel 란으로 들어가시면 keil 용으로 포팅된 포팅소스가 있습니다.

그중에서 uCOS-ii 버젼 V2.52 용으로 된것을 이용하도록 하겠습니다.

제가 가지고 있던건 V2.51 인데... 별차이가 없기에..^^ 그냥 쓰셔도 됩니다.

만약에 다른 버젼의 uCOS-ii 소스를 가지고 계시다면 다른걸 받으셔도 무방합니다.

( 다운받으신 포팅소스에는 포팅화일만 있습니다. uCOS-ii 소스 화일은 Jean Labrosse님께서 쓰신 uCOS-ii 책에서

제공되는 CD에 있는 소스를 사용하시거나, 알아서 구하셔야 합니다...^^)



그럼 이제 포팅에 필요한 준비는 끝이 났습니다.


MPU : AT89S52 (ATEML社)

uCOS-ii 버젼: V2.51

컴파일러 : Keil v7.20



위와 같은 환경에 저번 포팅기에서 이야기했던,

uCOS-ii 포팅소스와 커널 소스를 가지고 포팅을 진행해 보도록하겠습니다.



각자 취향이라고 해야할까요??

취향마다 포팅시에 손대는 부분이 다를테니깐요..

저는 제방식대로 포팅을 진행하도록 하겠습니다.



이미 포팅이 되어있는 소스를 가지고 시작하는 것이기에...

어려운 일은 아니니 천천히 따라해보면 쉽습니다.



그럼 이제 AT89S52의 외부 프로그램 메모리와 외부 데이터 메모리에 포팅을 시작해 보도록 하겟습니다.



우선, 준비된 화일들을 다시한번 확인해 보도록 하겠습니다.



uCOS-ii 포팅소스:

<a href="http://www.ucos-ii.com/contents/products/ucos-ii/downloads/keil%20uCOS_II%20v2.52%20port.zip">http://www.ucos-ii.com/contents/products/ucos-ii/downloads/keil%20uCOS_II%20v2.52%20port.zip</a>



위 화일을 받으신후 압축을 푸시면 여러 화일들이 나옵니다.

그중에서 아래의 화일들만 분리해서 이제 포팅을 진행할 폴더에 복사하시기 바랍니다.

예) c:\keil\engine\ucos\port



INCLUDES.H -> 마스터 인클루드 화일 헤더화일들의 대표입죠..^^

OS_CFG.H -> OS 환경 설정 헤더 화일

OS_CPU.H -> OS CPU의존적인 설정 환경화일

OS_CPU_A.A51 -> OS CPU 의존적인 어셈화일

OS_CPU_C.C -> OS CPU 의존적인 C화일

os_kc51.h -> OS Keil 의존적인 헤더화일

os_kcdef.h -> OS Keil 의존적인 define 설정화일

EX1L.C -> main 함수가 들어있는 화일

uCOS_II.H -> uCOS_ii 정의 화일



받으신 포팅소스는 Keil에서 지원하는 PC에뮬레이터 소스가 같이 첨부되어 있는데...

불필요한 소스이기에 쓰지 않도록 하겠습니다.



uCOS-ii 커널소스:

커널 소스는 커널소스 폴더에 넣으시기 바랍니다.

예)c:\keil\engine\ucos\source



작업폴더는 c:\keil\engine\ucos 이곳이 되며, 이곳에 Keil 프로젝트 화일을 생성하시기 바랍니다.





/*************************************** 작업의 시작 1 ******************************************/



주의1: 포팅시에 에러가 난다고 해서, source 화일에 있는 ucos-ii 커널 소스는 절대 건드리시면 안됩니다. ^^



이제 포팅 소스들을 살펴보도록 하겠습니다.

아래에 보이는 소스는 ucos-ii.com 에서 받으신 소스를 AT89S52에 맞게 수정한 것입니다. 그러니 소스를 살펴보시면서

수정된 부분을 똑같이 수정하시기 바랍니다.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

< INCLUDES.H >



#ifndef __INCLUDES__
#define __INCLUDES__

#include <REGX51.H> //<-- AT89S52를 위한 헤더화일로 수정

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <setjmp.h>



/* These macros are intended to be used to re-declare the uC/OS-II functions to be reentrant */
#define TASK_REENTRANT large reentrant
#define KCREENTRANT large reentrant

#include "os_cpu.h"
#include "os_cfg.h"



/* These Keil keywords are used in uC/OS-II source files. So the next macro definitions are needed */
#define data ucos51_data
#define pdata ucos51_pdata
#define xdata ucos51_xdata

#include "ucos_ii.h"
#include "os_kc51.h" /* MUST NOT REMOVE THIS LINE */


#endif

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Includes.h 화일은 우리가 사용하게될 헤더화일들을 모아놓은 화일입니다.

그러니 나중에 헤더화일들을 일일이 인클루드 시킬 필요없이 이 화일만 추가 시키면 됩니다.

처음에 __INCLUDES__ 를 선언해줌으로써 includes.h 라는 화일이 두번 호출되는걸 막는 부분으로 시작이 됩니다.

AT89S52의 레지스터가 정의된 REGX51.H 화일와 표준 라이브러리 헤더화일들을 인클루드 시켰습니다.



#define TASK_REENTRANT large reentrant
#define KCREENTRANT large reentrant



Keil 컴파일러는 재진입을 기본적으로 지원하지 않기에 재진입함수에는 large reentrant 라는 KEYWORD를 사용하게 됩니다.

large는 메모리 모델을 말하며, 외부 데이터 메모리에 reentrant 스택을 사용함을 말합니다.

재진입시에는 함수에서 선언된 데이터 변수들을 스택에 새로 잡아서 사용하게되며,

동일한 함수의 클론이 생성된다고 생각하면 됩니다.



reentrant가 지정되지 않게 되면, 함수의 재진입시, 진입 이전의 변수및 레지스터를 공유하게 되며, 컴파일시 재진입함수의 경고

메시지도 출력이 됩니다.



#define data ucos51_data
#define pdata ucos51_pdata
#define xdata ucos51_xdata



data, pdata, xdata 는 Keil 컴파일러의 KEYWORD로 사용되고 있지만, uCOS-ii 소스에서 사용되는 이름이기도 합니다.

그렇기 때문에 여기서 data라는 키워드가 사용되게 되면, 내부 데이터 영역을 가르키는게 아니라 ucos51_data라는

이름으로 변경하게 만들어서 uCOS-ii 소스의 변경없이 사용하도록 하였습니다.

(data 및 pdata 는 매개변수로 함수에 넘겨줄대 ucos-ii에서 동일한 이름으로 사용하고 있습니다.)

나중에 사용자가 data , pdata , xdata 라는 키워드를 사용하고 싶을때는 "os_kcdef.h" 헤더화일을 추가해서

data, pdata, xdata를 undef 시켜서 사용하도록 합니다.



다음 포팅기에서는 다른 화일들을 또 살펴보도록 하겠습니다.

화일들을 살펴보면서 조금씩 수정되는 부분이 있으니, 이렇게 조금씩 수정해 나가면서

전체 포팅화일들을 쭉~ 살펴보고, 프로젝트 화일에서 컴파일 옵션만 설정해주면....

포팅과정이 끝나게 됩니다...^^

 

< OS_KC51.H >

OS_KC51.h 헤더화일은 uCOS_ii.h 헤더화일에서 reentrant 한 함수들에 대해서 Keil 문법에 맞게

함수들의 프로토타입을 재정의해 놓았습니다.

이곳에서 재정의된 reentrant 함수들을 uCOS-ii 소스화일에도 똑같이 수정해 주어야 합니다.



....
#if OS_TASK_CREATE_EN > 0
INT8U OSTaskCreate(void (*task)(void *pd) KCREENTRANT, void *pdata, OS_STK *ptos, INT8U prio) KCREENTRANT;
#endif

...



OS_KC51.h의 일부분중 OSTaskCreate 함수가 KCREENTRANT 로 재정의가 되어있습니다.

(KCREENTRANT는 large reentrant 로 정의 되어있죠??)

그렇다면 우리는 OSTaskCreate함수가 정의되어있는 OS_TASK.c 화일에서

OSTaskCreate 함수에 KCREENTRANT를 추가해서 수정해 주어야 합니다.



이렇게 나머지 재정의 함수들에 대해서도 소스화일에서 KCREENTRANT 를 추가해주시기 바랍니다.

이부분에서만 uCOS-ii 소스 화일을 수정하시고 이후에는 절대 수정하시면 안됩니다...^^



< OS_CFG.H >

이 화일은 uCOS 환경설정 화일입니다.


#define OS_MAX_EVENTS 2 /* Max. number of event control blocks in your application ... */
/* ... MUST be > 0 */
#define OS_MAX_FLAGS 2 /* Max. number of Event Flag Groups in your application ... */
/* ... MUST be > 0 */
#define OS_MAX_MEM_PART 4 /* Max. number of memory partitions ... */
/* ... MUST be > 0 */
#define OS_MAX_QS 2 /* Max. number of queue control blocks in your application ... */
/* ... MUST be > 0 */
#define OS_MAX_TASKS 8 /* Max. number of tasks in your application ... */
/* ... MUST be >= 2 */


포팅소스의 OS_CFG.h 화일을 열어보시면 위와 같은 식으로 정의 되어있는 걸보실수 잇습니다

주석이 옆에 잘달려 있어서 어떤 정의를 하고 있는지 쉽게 알수 있습니다...^^



OS 이벤트, 태스크등의 갯수는 몇개로 할것이며, 어떤 함수들을 사용할것이냐 등등...

이부분의 설정은 커널사이즈에 영향을 미치게 되니, 찬찬히 살펴 보시면서 각각 설정해주시기 바라며

여기서는 포팅소스의 아랫부분에 정의된 클록 부분만 수정을 하도록 하겠습니다.



#define OS_TICKS_PER_SEC 50 /* Set the number of ticks in one second */


이부분은 OS_TICK을 1초에 몇번을 실행시키느냐 하는 부분인데...저희는 50으로 설정하도록 하겠습니다.

Tick은 1초에 50번 울리게 되며, 실행시마다 스케쥴링을 하게 됩니다.



< OS_CPU.H >



위 화일은 uCOS의 CPU 의존적인 설정이 들어있습니다.

uCOS에서 사용하게될 데이터 형들에 대한 정의와 크리티컬 영역의 진입 방법 설정하는 부분등이 있습니다.

많은 양의 코드가 들어있지 않기에 쑥 살펴 보시기 바랍니다.





이제 OS_CPU_A.a51 화일과 OS_CPU_C.c 화일만 남았습니다..

이 두화일이 가장 신중히 살펴보아야 할곳입니다.



<OS_CPU_C.C>

=============================================================================================================

OS_CPU_C.C 화일에서는 컴파일러및 MCU에 종속적인 C함수들을 정의하고 있습니다.



OS_STK *OSTaskStkInit (void (*task)(void *pd) KCREENTRANT, void * vd, OS_STK *ptos, INT16U opt) KCREENTRANT



OSTaskStkInit 함수가 있습니다. 이 함수는 OSTaskCreate 함수를 사용해서 태스크를 생성할때 호출되는 함수로서,

인자로 받는 스택에 가상의 초기 스택프레임을 만들어 줍니다.

처음 인자로 받는 void (*task)(void *pd) KCREENTRANT 는 KCREENTRANT로 선언된 함수의 포인터 입니다.

void (*task)(void *pd) 는 함수의 포인터를 가르키며, 인자로 포인터를 받는 함수 포인터 입니다.

(모르신다면, C언어 책을 참고해 보시길...)



그 다음 두번째 인자인 void *vd 는 *task 포인터가 받는 인자값을 받게 됩니다.

OS_STK *ptos 는 스택의 시작포인터를 넘겨 받습니다.

그리고 INT16U opt 는 태스크의 우선순위 값입니다.



그럼 스택의 모양을 어떻게 만드는지 보도록 합시다.

여기서 만들게 되는 스택의 모양은 태스크스위칭시에 스택을 푸쉬팝하는 모양과 같아야합니다. ^^

그러므로 이부분에서 스택의 모양을 잘잡아주어야 합니다.



OS_STK *OSTaskStkInit (void (*task)(void *pd) KCREENTRANT, void * vd, OS_STK *ptos, INT16U opt) KCREENTRANT
{
INT8U * stk;

opt = opt; /* 'opt' is not used, prevent warning */
stk = (INT8U *) ptos; /* Load stack pointer */

stk -= sizeof(void *); /* Save the vd to external stack */
*(void**)stk = vd; /* */

stk -= sizeof(INT16U); /* The value should be loaded to PC */
*(INT16U*)stk = (INT16U) task; /* next time when this task is running */



/* Following is the registers pushed into hardware stack */
*--stk = 'A'; /* ACC */
*--stk = 'B'; /* B */
*--stk = 'H'; /* DPH */
*--stk = 'L'; /* DPL */
*--stk = PSW; /* PSW */
*--stk = 0; /* R0 */

stk -= sizeof(void *); /* Keil C uses R1,R2,R3 to pass the */
*(void**)stk = vd; /* arguments of functions. */

*--stk = 4; /* R4 */
*--stk = 5; /* R5 */
*--stk = 6; /* R6 */
*--stk = 7; /* R7 */

/* Following is the registers pushed into hardware stack manually to support the dallas 390 */
*--stk = 0x80; /* IE, EA is enabled */
/* Next is calculating the hardware stack pointer. */
*--stk = (INT8U) STACK_START-1 /* Initial value when main was called */
+1 /* IE */
+8 /* R0-R7, eight registers was saved */
+5 /* ACC, B, DPH, DPL, PSW, five registers */
+sizeof(INT16U) /* The PC value to be loaded */
;

return ((void *)stk);
}



스택초기화 함수를 위와 같이 AT89S52에 맞게 변경하였습니다. 현재 저희가 받은 포팅소스는 Dallas390에 포팅된 소스라서

기본적으로 8051코어를 사용하지만 추가된 레지스터가 몇개 있고, 또 PC(Program Counter)를 Dallas390은 24바이트사이즈를

사용하는 독특한 구조라서 변경해야 할 부분이 몇군데 있었습니다. 위와 같인 심플한 모양으로 변경하시기 바랍니다.



먼저 스택에 ACC, B, DPH, DPL, PSW, R0 ~ R7, 그리고 IE레지스터의 순으로 넣게 됩니다.

R1,R2,R3 레지스터는 Keil에서는 함수의 아규먼트 부분으로 사용되며, R3, R2, R1을 차례대로 꺼낼때 (void *) 형의 vd 값이 호출되게 됩니다. vd는 Generic 한 포인터 형으로서 Keil에서는 Generic 한 포인터의 매개변수는 R1,R2,R3을 사용하게 됩니다. ^^

(이부분은 Keil C에서 제공하는 C51.pdf에 보면 잘나와있습니다.)



그리고 IE레지스터에서 EA인터럽트 인에이블을 허용한 상태로 넘기게 되는데요..

만약 이부분에서 인터럽트를 인에이블 시키지 않아놓으면, 태스크 스위칭할때 인터럽트가 디스에이블상태로

되기때문에 태스크스위칭한후에는 틱함수가 불리지 않게 되게 됩니다. 인에이블 시켜야하겠죠.



*--stk = (INT8U) STACK_START-1 /* Initial value when main was called */
+1 /* IE */
+8 /* R0-R7, eight registers was saved */
+5 /* ACC, B, DPH, DPL, PSW, five registers */
+sizeof(INT16U) /* The PC value to be loaded */
;



STACK_START 는 내부 데이터 변수로 선언된 스택의 시작번지를 가르키고 있으며, OS_CPU_A.a51 화일에 정의되어

있습니다. 그래서 extern 으로 설정되어있죠.



extern idata unsigned char STACK_START[1];



우리가 초기에 만든 스택 모양의 제일 마지막에는 외부에 정의된 스택의 내용을 내부스택에 넣기위해서 총 push된 스택의 크기가

저장되게 됩니다.



이부분이 가장 중요한 스택프레임 만드는 부분이였고, 다른 부분도 살펴보죠. ^^



extern INT8U xdata * data C_XBP;



앞으로 많이 보게될 C_XBP입니다. 이는 외부에 선언된 스택의 포인터입니다.




void OSStartHighRdy(void) KCREENTRANT
{
OSTaskSwHook();
OSRunning=1;

C_XBP=OSTCBHighRdy->OSTCBStkPtr;

LoadCtx();
}



이부분에서는 OSSTART 함수에서 호출되며, 현재 가장 우선순위가 높은 스택의 포인터를 C_XBP에 저장한 후에

Context Switching 을하게 됩니다.



void C_OSCtxSw(void) KCREENTRANT
{


OSTCBCur->OSTCBStkPtr = C_XBP;

OSTaskSwHook();
OSTCBCur = OSTCBHighRdy;
OSPrioCur = OSPrioHighRdy;

C_XBP = OSTCBCur->OSTCBStkPtr;
LoadCtx();
}



C_OSCtxSw(void) 함수는 C함수에서 호출하는 문맥전환 함수입니다. 이 함수도

문맥전환을 위해서 LoadCtx()함수를 호출하게 됩니다.



void OSIntCtxSw(void) KCREENTRANT
{
EA=0;
SP=SaveSP;

C_XBP=OSTCBCur->OSTCBStkPtr;

#pragma ASM
EXTRN CODE(_?KCOSCtxSw)
MOV A, #LOW _?KCOSCtxSw
PUSH ACC
MOV A, #HIGH _?KCOSCtxSw
PUSH ACC
RETI
#pragma ENDASM
}



OSIntCtxSw(void) 함수는 인터럽트 루틴에서 호출하는 문맥전환 함수입니다.

위 어셈명령어를 간단히 소개하자면, OS_CPU_A.a51에 정의된 _?KCOSCtxSw 함수의

주소를 ACC를 이용해서 push 한다음에 RETI 명령을 수행하게 되면,

KCOSCtxSw로 되돌아가게 됩니다. ^^



void OSTickISR(void) interrupt 1
{
/* Do this first */
OSIntNesting++; /* Increment ISR nesting level directly to speed up processing */
// OSIntEnter(); /* Must be called first at every hardware interrupt entry point */
if(OSIntNesting==1) /* Only at the outerest interrupt we do these. */
{
#pragma ASM
PUSH IE
#pragma ENDASM
EA=0;
SaveSP=SP;
OSTCBCur->OSTCBStkPtr=C_XBP; /* OSTCBCur->OSTCBStkPtr is free now, so it can be used to story the value of SP */
EA=1;
}
OSTimeTick(); /* Must be called during tick isr */
OSIntExit(); /* Must be called finally at every hardware interupt exit point */
if(OSIntNesting==0)
{
EA=0;
C_XBP=OSTCBCur->OSTCBStkPtr;
SP=SaveSP;
#pragma ASM
POP IE
#pragma ENDASM
}
}



OS_CPU_C.c 화일에는 Tick 인터럽트 함수가 선언되어있습니다.

void OSTickISR(void) 함수가 바로 Tick 함수로서 이부분에서 OS Tick 을 증가시켜,

스케쥴링함수를 호출합니다.



void SerialIntr(void) interrupt 4
{
/* Do this first */
OSIntNesting++; /* Increment ISR nesting level directly to speed up processing */
// OSIntEnter(); /* Must be called first at every hardware interrupt entry point */
if(OSIntNesting==1) /* Only at the outerest interrupt we do these. */
{
#pragma ASM
PUSH IE
#pragma ENDASM
EA=0;
SaveSP=SP;
OSTCBCur->OSTCBStkPtr=C_XBP; /* OSTCBCur->OSTCBStkPtr is free now, so it can be used to story the value of SP */
EA=1;
}


/* Next you can do something for yourself. */
/* Finally, before exit from ISR, must do as following. */
OSIntExit(); /* Must be called finally at every hardware interupt exit point */
if(OSIntNesting==0)
{
EA=0;
C_XBP=OSTCBCur->OSTCBStkPtr;
SP=SaveSP;
#pragma ASM
POP IE
#pragma ENDASM
}
}


void SerialIntr(void) 함수는 포팅한 사람이 만들어 놓은 시리얼통신 인터럽트 프로그램으로

사용하셔도 되고 지우셔도 되고 편하신대로 하시면됩니다.

사용자 인터럽트를 정의할때는 OSIntEnter() 함수와 OSIntExit() 함수를 사용하시고, OSIntNexting 변수로

중첩 인터럽트에 대한 정보를 처리하시면 됩니다.

참고하자면, 위에서 설명한 Tick 함수나 시리얼 인터럽트 서비스루틴에서는 OSIntEnter 함수의 사용대신에

직접 OSIntNesting 변수를 증가시켜주었죠?? 좀더 속도향상을 위해서...



OS_CPU_C.c 화일에는 이외에 Hook함수가 몇개 정의 되어있는데,

빈껍데기에 불과하고, 사용자가 필요할때 정의해서 쓰시면됩니다.



위에서 제가 Dallas390으로 포팅된 소스를 전부 변경했습니다. 위에서 설명하지 않은 함수들은

그냥 변경없이 쓰시면됩니다.

^^ 별로 크게 바꾸거나 변경한 부분은 없기 때문에 쭉 살펴보시기 바랍니다.

그럼 이상 OS_CPU_C.c 화일에 대한 설명은 마치고

다음에는 OS_CPU_A.a51 함수도 좀 손을 보도록해서 포팅기의 마지막으로 가도록 하겠습니다.

 

<OS_CPU_A.a51>

=================================================================================================================


$NOMOD51


OS_CPU_A.a51 소스의 제일 위에는 $NOMODE51 이라는 지시어가 적혀있습니다.

이를 주석처리를 하거나 지워주시기 바랍니다.

Dallas390은 어셈블리어를 컴파일할때 AX51을 사용하였고, AX51은 Pre-Define 된 8051 레지스터들을 사용하지 않고,

자체적으로 사용하기에 위 옵셥을 줘야했지만, AT89S52는 A51 컴파일러를 사용할것이기에 위 옵션을 생략하도록 하겠습니다.



PUBLIC ?C_XBP, C_XBP

EXTRN CODE(_?C_OSCtxSw)

PUBLIC _?LoadCtx, STACK_START, _?OSCtxSw, _?KCOSCtxSw



LoadXBP MACRO
MOV DPH, C_XBP
MOV DPL, C_XBP+1
ENDM

SaveXBP MACRO
PUSH IE
CLR EA
MOV C_XBP, DPH
MOV C_XBP+1, DPL
POP IE
ENDM

LoadREG MACRO REG
MOVX A, @DPTR
MOV REG, A
ENDM

SaveREG MACRO REG
MOV A, REG
MOVX @DPTR, A
ENDM

; The PUSHA now emulates the pushing sequence what Keil C does.
PUSHR MACRO
IRP REG, <ACC, B, DPH, DPL, PSW, 0, 1, 2, 3, 4, 5, 6, 7>
PUSH REG
ENDM
ENDM

POPR MACRO
IRP REG, <7, 6, 5, 4, 3, 2, 1, 0, PSW, DPL, DPH, B, ACC>
POP REG
ENDM
ENDM



위 소스들은 OS_CPU_A.a51에서 사용하게될 메크로 들입니다.

LoadXBP 메크로는 외부스택포인터(C_XBP)의 포인터를 DPH, DPL에 로드하는 메크로입니다.

외부에 우리가 잡아놓은 테스크스택의 위치를 가져와서 내부스택으로 Context 를 옮기는 경우에 사용됩니다.

SaveXBP는 LoadXBP의 반대이겠죠?? ^^

LoadREG는 REG에 매개변수로 받은 레지스터에 DPTR에서 로드되는 값을 넣게 됩니다.

SaveREG는 역시 그 반대죠...



PUSHR 과, POPR 메크로는 Context Swithing 할때, 스택에 푸쉬하고 팝하는 이중메크로입니다. ^^

저 순서는 우리가 OS_STK *OSTaskStkInit 함수에서 잡아주었던 스택의 모양과 동일해야겠죠??



; Declare the external stack pointer by ourself, so that we can use it freely.
; you know, in the name of '?C_XBP' it can not be used in c modules but in the
; name of 'C_XBP' it can do.

DT?C_XBP SEGMENT DATA
RSEG DT?C_XBP
?C_XBP: ; These two labels point to the same address
C_XBP: ;
DS 2

; Declare a label 'Stack' in the hardware stack segment so that we know where it begins.
?STACK SEGMENT IDATA
RSEG ?STACK
STACK_START:
DS 1



C_XBP는 외부 데이터에 위치한 태스크스택의 주소값을 저장하는 공간으로 사용되고,

STACT_START 는 내부 스택포인터의 위치를 갖게 됩니다.

좀더 부연 설명을 하자면,

?C_XBP를 위해서 DT_?C_XBP라는 재배치가능한 세그먼트를 생성한후에

?C_XBP의 값을 스타트업 코드에서 넘겨받게 됩니다. (스타트업 코드 참조...)

?C_XBP나 C_XBP나 동일한 값이며, ?C_XBP는 C함수에서는 호출이 불가능하므로, C_XBP를 C에서 사용하게됩니다.

(위에 주석이 잘되어있죠?? ^^_

물론 STACK_START도 같은 식이죠....





; Load context from the external stack pointed by C_XBP
PR?LoadCtx SEGMENT CODE
RSEG PR?LoadCtx
_?LoadCtx:
LoadXBP ; Load the C_XBP to DPTR

LoadREG SP ; Load the hardware stack pointer
INC DPTR ;

MOV R0, SP ; Now we pop the hardware stack
LC_1: ; from the external one.
LoadREG @R0 ; Did not use the PUSH ACC instruction for if we want to
INC DPTR ; do so, we have to DEC DPTR, which costs much.
DEC R0 ;
CJNE R0, #STACK_START-1, LC_1 ;

SaveXBP ; after the hardware stack has been popped,
; the external stack pointer should be adjusted

RestoreCtx:
WANTFASTER EQU 1
$IF WANTFASTER
POP PSW ; A little bit dangerous but it works. C is PSW.7 and EA is IE.7
MOV EA, C ; They are at the same bit location of a byte.
$ELSE
POP ACC ; Safe way to do the same thing.
RLC A ;
MOV EA, C ;
$ENDIF
; Now that the context has been loaded into hardware
POPR ; stack, what we need do is just popping them upto registers.
;

RET ; Now everything is ready, a RET will bring the task to run.

; Task level context switch entry point, which is intended to be called by task gracefully.
_?OSCtxSw:
PUSHR ; Save current context first into hardware stack
PUSH IE

_?KCOSCtxSw: ; Now begin pushing hardware stack to external one
LoadXBP ; Load the external stack pointer first to prepare storing
; data into it.

MOV A, SP ; Calculate how much memory in external stack needed
CLR C ; so that we can adjust the external stack pointer
SUBB A, #STACK_START-1 ; Calculated the length of hardware stack

MOV R0, A ; Save the length of hardware stack to R0, which is used as a counter on saving hardware stack.

NC A ; Add the space for storing SP

CLR C
XCH A, DPL ; Now ACC contains the right amount of external stack memory should be used.
SUBB A, DPL ; Adjust the external pointer.stored in DPTR to make to point to the new stack top

; from where we will store hardware stack.
JNC SC_1
DEC DPH
SC_1:
MOV DPL,A ; Now DPTR contains the external stack pointer after pushing context into external stack.

SaveXBP ; Save to external stack pointer.
; Keeps the DPTR containing the external stack pointer still.
SaveREG SP ; Save hardware stack pointer in the top of external stack

SC_2:
INC DPTR ;
POP ACC ; Pop the data from hareware stack
MOVX @DPTR, A ; and save into external one.
DJNZ R0, SC_2 ; Remember, R0 contains the hardware stack's length.

LJMP _?C_OSCtxSw ;




위 소스가 수정된 소스입니다...^^

달라진 부분은 별루 없구요... AX51문법으로 된 #BYTE0 (STACK_START-1) 이런문법을 바꾼거 밖엔 없네요...



그외에 위에 메크로 조금 수정한거...^^

문맥의 저장, 로드, 스위칭에 관련된 부분인데, 상당히 짧기에 별설명없이 쭉 훍어보시면 이해가가시리라 믿습니다.

대략 설명하자면,

_?LoadCtx: 함수같은 경우는 외부스택에 저장된 문맥들을 내부스택으로 옮겨와서,

POPR 메크로를 사용해서 태스크스위칭을 하게되는 부분입니다. ^^

_?KCOSCtxSw 같은 경우는 그 반대이구요... ^^

쭉 명령어들을 따라가시면서 분석해보세요...어렵지 않습니다...



그럼 이걸로 OS_CPU_A.a51 화일도 끝이 났네요...



그럼 이제 다음 포팅기에서는 이제까지 살펴본 화일들을 이용해서, 실제로 포팅을 해보는 일만 남았네요.



정말 짧게 쓰고자했던 포팅기였는데 생각보다 넘 길어져서...당황스럽네요...^^;



그럼 다음에는 스타트업코드를 살짝쿵 살펴보고 마무리를 짓죠...

이제 해야할 일은, 지금까지 AT89S52에 맞게 수정했던 화일들을 가지고,

스타트업코드와 함께 컴파일 하는 일만 남았군요....^^



스타트업코드는 Keil 컴파일러에서 기본적으로 제공해주는 코드를 사용하도록 하겠습니다.



Keil 컴파일러가 설치되어있는 아래 폴더에서 STARTUP.A51 화일을 우리가 작업하는 폴더로 복사하시기 바랍니다.

C:\Keil\C51\LIB\STARTUP.A51



이제 STARTUP.A51 에서 우리가 살펴보아야 할부분만 보도록 하죠~



<STARTUP.a51>

=================================================================================================================

; ; the absolute start-address of IDATA memory is always 0
IDATALEN EQU 80H ; the length of IDATA memory in bytes.

XDATASTART EQU 8000H ; the absolute start-address of XDATA memory
XDATALEN EQU 8000H ; the length of XDATA memory in bytes.

PDATASTART EQU 0H ; the absolute start-address of PDATA memory
PDATALEN EQU 0H ; the length of PDATA memory in bytes.


스타트업 코드를 보시면 위와 같이 데이터 영역의 크기와 시작 번지를 지정하는 부분이 있습니다.

IDATALEN은 내부 데이터의 크기를 나타내고, 시작번지는 언제나 0번지라고 친절하게 주석이 달려있죠??

XDATASTART 외부데이터의 시작번지는 8000번지로 잡겠습니다.(8000번지부터 FFFF번지까지 램영역으로 잡자.)

XDATALEN 외부데이터의 크기는 32Kbyte인 8000h로 설정하겠습니다.

PDATA 영역은 우리는 사용하지 않기때문에 0으로 설정해둡니다.



; Stack Space for reentrant functions in the SMALL model.
IBPSTACK EQU 0 ; set to 1 if small reentrant is used.
IBPSTACKTOP EQU 0FFH+1 ; set top of stack to highest location+1.
; Stack Space for reentrant functions in the LARGE model.
XBPSTACK EQU 1 ; set to 1 if large reentrant is used.
XBPSTACKTOP EQU 0FFFFH+1 ; set top of stack to highest location+1.
; Stack Space for reentrant functions in the COMPACT model.
PBPSTACK EQU 0 ; set to 1 if compact reentrant is used.
PBPSTACKTOP EQU 0FFFFH+1 ; set top of stack to highest location+1.



이부분은 이제 c에서 사용할 reentrant 펑션을 위한 스택공간을 설정하는 부분입니다.

역시 주석에 따라서 설정을 위와같이 해주시면 됩니다.

XBPSTACK 의 값을 1로 했을때, 사용하겠다는 의미이고, XBPSTACK은 Large 메모리 모드에서

사용하는 외부스택입니다.



그 위에 쭉 스타트업 코드를 살펴보시면, 메모리를 초기화 하는 부분이 있고,

마지막에 스택포인터를 설정해주고 C함수의 main으로 점프를하게됩니다.


IF XDATALEN <> 0
MOV DPTR,#XDATASTART
MOV R7,#LOW (XDATALEN)
IF (LOW (XDATALEN)) <> 0
MOV R6,#(HIGH (XDATALEN)) +1
ELSE
MOV R6,#HIGH (XDATALEN)
ENDIF
CLR A
XDATALOOP: MOVX @DPTR,A
INC DPTR
DJNZ R7,XDATALOOP
DJNZ R6,XDATALOOP
ENDIF

위 코드가 외부 데이터를 초기화 하는 부분이죠...^^



IF XBPSTACK <> 0
EXTRN DATA (?C_XBP)

MOV ?C_XBP,#HIGH XBPSTACKTOP
MOV ?C_XBP+1,#LOW XBPSTACKTOP
ENDIF



이코드는 EXTERN 으로 선언된 ?C_XBP에 위에서 설정해주었던, XBPSTACKTOP의 값을

넣어주는 부분입니다.

?C_XBP는 우리가 OS_CPU_A.a51 화일에서 보았었죠?? ^^

이곳에서 그 값을 넣어주게 됩니다.



MOV SP,#?STACK-1

그리고 마지막 부분에는 이런식으로 내부데이터메모리에서 스택스그먼트의 시작주소를

스택에 집어넣고 C로 점프하게 됩니다.

8051에서 스택의 위로 자라게 되죠... 그러므로 ?STACK 세그먼트가 자리잡게 되는 위치는

내부데이터의 마지막 부분에 자리잡게 됩니다.

============================================================================================

이제 스타트업 코드도 살펴보았고 컴파일을 해보도록 하겠습니다.





그럼 Keil 프로젝트 화일을 만들어서 아래와 같은 화일들을 등록하시기 바랍니다.

=================================

uCOS_ii.C

OS_CPU_C.c

OS_CPU_A.a51

main.c

task.c

STARTUP.a51

=================================

uCOS_ii.C 화일에는 ucosii 소스화일들이 인클루드되어 있어서, uCOS_ii.c 화일을 컴파일하게 되면,

uCOSii 소스화일들이 전부 컴파일이 됩니다.

그리구 우리가 포팅한 OS_CPU_C 와 OS_CPU_A 화일도 등록을 해주시고요...

그리고 제가 간단하게 만들어놓은 task.c 화일도 등록을 해놓겠습니다.

task.c 화일은 간단하게 태스크들을 정의해 놓았습니다.



이제 프로젝트 옵션에 가셔서 프로젝트 옵션을 설정해야합니다.

Device : AT89S52 (LX51, AX51 은 사용하지 않습니다.)

Target : 메모리 모델과 코드 모델은 LARGE 입니다.

offchip 코드 메모리는 0x0000 ~ 0x7ffff

offchip 데이터 메모리는 0x8000 ~ 0xffff

C51 : 컴파일 레벨은 정당히 설정하세요... ^^

A51 : SFR names는 Define 시킵니다.

BL51 : 타겟 다이알로그에 있는 세팅을 사용합니다.



이제 컴파일 하신후에 디버깅 모드에서

멀티태스킹이 되시는 모습을 보시기 바랍니다. ^^

Keil 컴파일러에서 제공하는 시뮬레이터는 실제와 상당히 정확해서...

시뮬레이터만 이용해도 디버깅하기에 충분합니다. 만약 생각되로 잘 움직이지 않는다면,

디버깅 모드에서 Step in 으로 찬찬히 살펴보시면 어디가 잘못된지 금방 보일테니...

끈기를 가지고 포팅해보시기 바랍니다.



이상으로 포팅기를 마치고, 포팅된 소스들을 전부 모아서 압축화일로 등록을 해놓겠습니다.



가끔씩 생각날때, 짬날때 쪼금씩 적다가 보니...

중간 중간 빼먹은게 있지 않나 생각도 되고, 잘못된 부분도 있을거 같네요...^^



잘못된 부분이 있거나 의문되시는 부분은 직접 리플이나, 메일로 연락주시면, 바로 수정하거나

답변을 드리도록 하겠습니다.



그럼 즐거운 포팅되세요~



 


 

 

'c or linux' 카테고리의 다른 글

How to be a Programmer : A short....  (0) 2006.07.20
C를 C++처럼 사용하기  (0) 2006.07.20
좋은 구조체 리턴 함수  (0) 2006.04.15
&, && 및 우선순위 주의  (0) 2006.03.28
영어 축약어  (0) 2006.02.15
Posted by '김용환'
,