diff options
Diffstat (limited to 'qpid/doc/book/src/old/NET-User-Guide.xml')
| -rw-r--r-- | qpid/doc/book/src/old/NET-User-Guide.xml | 1383 |
1 files changed, 0 insertions, 1383 deletions
diff --git a/qpid/doc/book/src/old/NET-User-Guide.xml b/qpid/doc/book/src/old/NET-User-Guide.xml deleted file mode 100644 index 7bfa20b8c8..0000000000 --- a/qpid/doc/book/src/old/NET-User-Guide.xml +++ /dev/null @@ -1,1383 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - ---> - -<section> - <title> - Apache Qpid: Open Source AMQP Messaging - .NET User Guide - </title> - <section role="h1" id="NETUserGuide-Tutorial"> - <title> - Tutorial - </title> - <para> - This tutorial consists of a series of examples using the three - most commonly used exchange types - Direct, Fanout and - Topic - exchanges. These examples show how to write applications that use - the most common messaging paradigms. - </para> - <itemizedlist> - <listitem> - <para>direct</para> - <para>In the direct examples, a message producer writes to the direct - exchange, specifying a routing key. A message consumer reads - messages from a named queue. This illustrates clean separation - of concerns - message producers need to know only the exchange - and the routing key, message consumers need to know only which - queue to use on the broker. - </para> - </listitem> - <listitem> - <para>fanout</para> - <para>The fanout examples use a fanout exchange and do not use - routing keys. Each binding specifies that all messages for a - given exchange should be delivered to a given queue. - </para> - </listitem> - <listitem> - <para>pub-sub</para> - <para>In the publish/subscribe examples, a publisher - application writes messages to an exchange, specifying a - multi-part key. A subscriber application subscribes to - messages that match the relevant parts of these keys, using a - private queue for each subscription. - </para> - </listitem> - <listitem> - <para>request-response</para> - <para>In the request/response examples, a simple service accepts - requests from clients and sends responses back to them. Clients - create their own private queues and corresponding routing keys. - When a client sends a request to the server, it specifies its - own routing key in the reply-to field of the request. The - server uses the client's reply-to field as the routing key for - the response. - </para> - </listitem> - </itemizedlist> - <section role="h2" id="NETUserGuide-RunningtheExamples"> - <title> - Running the - Examples - </title> - <para> - Before running the examples, you need to unzip the file - Qpid.NET-net-2.0-M4.zip, the following tree is created: - </para> - - - <programlisting> -<home> - |-qpid - |-lib (contains the required dlls) - |-examples - |- direct - | |-example-direct-Listener.exe - | |-example-direct-Producer.exe - |- fanout - | |-example-fanout-Listener.exe - | |-example-fanout-Producer.exe - |- pub-sub - | |-example-pub-sub-Listener.exe - | |-example-pub-sub-Publisher.exe - |- request-response - |-example-request-response-Client.exe - |-example-request-response-Server.exe - </programlisting> - - - <para> - Make sure your PATH contains the directory - <home>/qpid/lib - The examples can be run by executing the provided exe files: - </para> - - - <programlisting> -$ cd <home>/qpid/examples/examplefolder -$ example-...-.exe [hostname] [portnumber] - </programlisting> - - - <para> - where [hostname] is the qpid broker host name - (default is localhost) and [portnumber] is the port number on which the - qpid broker is accepting connection (default is 5672). - </para> - <!--h2--> - </section> - - <section role="h2" id="NETUserGuide-CreatingandClosingSessions"> - <title> - Creating - and Closing Sessions - </title> - - <para> - All of the examples have been written using the Apache Qpid .NEt - 0.10 API. The examples use the same skeleton code to initialize - the program, create a session, and clean up before exiting: - </para> - - - <programlisting> -using System; -using System.IO; -using System.Text; -using System.Threading; -using org.apache.qpid.client; -using org.apache.qpid.transport; - -... - - private static void Main(string[] args) - { - string host = args.Length > 0 ? args[0] : "localhost"; - int port = args.Length > 1 ? Convert.ToInt32(args[1]) : 5672; - Client connection = new Client(); - try - { - connection.connect(host, port, "test", "guest", "guest"); - ClientSession session = connection.createSession(50000); - - //--------- Main body of program -------------------------------------------- - - connection.close(); - } - catch (Exception e) - { - Console.WriteLine("Error: \n" + e.StackTrace); - } - } -... - </programlisting> - <!--h2--> - </section> - - <section role="h2" id="NETUserGuide-WritingDirectApplications"> - <title> - Writing - Direct Applications - </title> - - <para> - This section describes two programs that implement direct - messaging using a Direct exchange: - • org.apache.qpid.example.direct.Producer (from - example-direct-producer) publishes messages to the amq.direct - exchange, using the routing key routing_key. - •org.apache.qpid.example.direct.Listener (from - example-direct-Listener) uses a message listener to receive - messages from the queue named message_queue. - </para> - <section role="h3" id="NETUserGuide-RunningtheDirectExamples"> - <title> - Running the - Direct Examples - </title> - <para> - 1) Make sure your PATH contains the directory - <home>/qpid/lib - </para> - <para> - 2) Make sure that a qpid broker is running: - </para> - - - <programlisting> -$ ps -eaf | grep qpidd - </programlisting> - - - <para> - If a broker is running, you should see the qpidd process in the - output of the above - command. - </para> - <para> - 3) Read the messages from the message queue using direct - listener, as follows: - </para> - - - <programlisting> -$ cd <home>/qpid/examples/direct - </programlisting> - - - <para> - With cygwin: - </para> - - - <programlisting> -$ ./example-direct-Listener.exe [hostname] [portnumber] - </programlisting> - - - <para> - or with mono: - </para> - - - <programlisting> -$ mono ./example-direct-Listener.exe [hostname] [portnumber] - </programlisting> - - - <para> - This program is waiting for messages to be published, see next - step: - </para> - <para> - 4) Publish a series of messages to the amq.direct exchange by - running direct producer, as follows: - </para> - - - <programlisting> -$ cd <home>/qpid/examples/direct - </programlisting> - - - <para> - With cygwin: - </para> - - - <programlisting> -$ ./example-direct-Producer.exe [hostname] [portnumber] - </programlisting> - - - <para> - or with mono: - </para> - - - <programlisting> -$ mono ./example-direct-Producer.exe [hostname] [portnumber] - </programlisting> - - - <para> - This program has no output; the messages are routed to the - message queue, as instructed by the binding. - </para> - <para> - 5) Go to the windows where you are running your listener. You - should see the following output: - </para> - - - <programlisting> -Message: Message 0 -Message: Message 1 -Message: Message 2 -Message: Message 3 -Message: Message 4 -Message: Message 5 -Message: Message 6 -Message: Message 7 -Message: Message 8 -Message: Message 9 -Message: That's all, folks! - </programlisting> - - - <para> - Now we will examine the code for each of these programs. In each - section, we will discuss only - the code that must be added to the skeleton shown in Section - "Creating and Closing Sessions". - </para> - <!--h3--> - </section> - - <section role="h3" id="NETUserGuide-ReadingMessagesfromtheQueue"> - <title> - Reading - Messages from the Queue - </title> - - <para> - The program , listener.cs, is a message listener that receives - messages from a queue. - </para> - <para> - First it creates a queue named message_queue, then binds it to - the amq.direct exchange using the binding key routing_key. - </para> - - - <programlisting> -//--------- Main body of program -------------------------------------------- -// Create a queue named "message_queue", and route all messages whose -// routing key is "routing_key" to this newly created queue. -session.queueDeclare("message_queue"); -session.exchangeBind("message_queue", "amq.direct", "routing_key"); - </programlisting> - - - <para> - The queue created by this program continues to exist after the - program exits, and any message whose routing key matches the key - specified in the binding will be routed to the corresponding - queue by the broker. Note that the queue could have been be - deleted using the following code: - </para> - - - <programlisting> -session.queueDelete("message_queue"); - </programlisting> - - - <para> - To create a message listener, create a class derived from - IMessageListener, and override the messageTransfer method, - providing the code that should be executed when a message is - received. - </para> - - - <programlisting> -public class MessageListener : IMessageListener -{ - ...... - public void messageTransfer(IMessage m) - { - ..... -} - </programlisting> - - - <para> - The main body of the program creates a listener for the - subscription; attaches the listener to a message queue; and - subscribe to the queue to receive messages from the queue. - </para> - - - <programlisting> -lock (session) -{ - // Create a listener and subscribe it to the queue named "message_queue" - IMessageListener listener = new MessageListener(session); - session.attachMessageListener(listener, "message_queue"); - session.messageSubscribe("message_queue"); - // Receive messages until all messages are received - Monitor.Wait(session); -} - </programlisting> - - - <para> - The MessageListener's messageTransfer() function is called - whenever a message is received. In this example the message is - printed and tested to see if it is the final message. Once the - final message is received, the messages are acknowledged. - </para> - - - <programlisting> -BinaryReader reader = new BinaryReader(m.Body, Encoding.UTF8); -byte[] body = new byte[m.Body.Length - m.Body.Position]; -reader.Read(body, 0, body.Length); -ASCIIEncoding enc = new ASCIIEncoding(); -string message = enc.GetString(body); - Console.WriteLine("Message: " + message); -// Add this message to the list of message to be acknowledged -_range.add(m.Id); -if( message.Equals("That's all, folks!") ) -{ - // Acknowledge all the received messages - _session.messageAccept(_range); - lock(_session) - { - Monitor.Pulse(_session); - } -} - </programlisting> - <!--h3--> - </section> - - <section role="h3" id="NETUserGuide-PublishingMessagestoaDirectExchange"> - <title> - Publishing - Messages to a Direct Exchange - </title> - <para> - The second program in the direct example, Producer.cs, publishes - messages to the amq.direct exchange using the routing key - routing_key. - </para> - <para> - First, create a message and set a routing key. The same routing - key will be used for each message we send, so you only need to - set this property once. - </para> - - - <programlisting> -IMessage message = new Message(); -// The routing key is a message property. We will use the same -// routing key for each message, so we'll set this property -// just once. (In most simple cases, there is no need to set -// other message properties.) -message.DeliveryProperties.setRoutingKey("routing_key"); - </programlisting> - - - <para> - Now send some messages: - </para> - - - <programlisting> -// Asynchronous transfer sends messages as quickly as -// possible without waiting for confirmation. -for (int i = 0; i < 10; i++) -{ - message.clearData(); - message.appendData(Encoding.UTF8.GetBytes("Message " + i)); - session.messageTransfer("amq.direct", message); -} - </programlisting> - - - <para> - Send a final synchronous message to indicate termination: - </para> - - - <programlisting> -// And send a syncrhonous final message to indicate termination. -message.clearData(); -message.appendData(Encoding.UTF8.GetBytes("That's all, folks!")); -session.messageTransfer("amq.direct", "routing_key", message); -session.sync(); - </programlisting> - <!--h3--> - </section> - - <!--h2--> - </section> - - - <section role="h2" id="NETUserGuide-WritingFanoutApplications"> - <title> - Writing - Fanout Applications - </title> - - <para> - This section describes two programs that illustrate the use of a - Fanout exchange. - </para> - <itemizedlist> - <listitem> - <para>Listener.cs makes a unique queue private for each instance of - the listener, and binds that queue to the fanout exchange. All - messages sent to the fanout exchange are delivered to each - listener's queue. - </para> - </listitem> - <listitem> - <para>Producer.cs publishes messages to the fanout exchange. It - does not use a routing key, which is not needed by the fanout - exchange. - </para> - </listitem> - </itemizedlist> - <section role="h3" id="NETUserGuide-RunningtheFanoutExamples"> - <title> - Running the - Fanout Examples - </title> - - <para> - 1) Make sure your PATH contains the directory - <home>/qpid/lib - </para> - <para> - 2) Make sure that a qpid broker is running: - </para> - - - <programlisting> -$ ps -eaf | grep qpidd - </programlisting> - - - <para> - If a broker is running, you should see the qpidd process in the - output of the above - command. - </para> - <para> - 3) In separate windows, start one or more fanout listeners as - follows: - </para> - - - <programlisting> -$ cd <home>/qpid/examples/direct - </programlisting> - - - <para> - With cygwin: - </para> - - - <programlisting> -$ ./example-fanout-Listener.exe [hostname] [portnumber] - </programlisting> - - - <para> - or with mono: - </para> - - - <programlisting> -$ mono ./example-fanout-Listener.exe [hostname] [portnumber] - </programlisting> - - - <para> - The listener creates a private queue, binds it to the amq.fanout - exchange, and waits for messages to arrive on the queue. When the - listener starts, you will see the following message: - </para> - - - <programlisting> -Listening - </programlisting> - - - <para> - This program is waiting for messages to be published, see next - step: - </para> - <para> - 4) In a separate window, publish a series of messages to the - amq.fanout exchange by running fanout producer, as follows: - </para> - - - <programlisting> -$ cd <home>/qpid/examples/direct - </programlisting> - - - <para> - With cygwin: - </para> - - - <programlisting> -$ ./example-fanout-Producer.exe [hostname] [portnumber] - </programlisting> - - - <para> - or with mono: - </para> - - - <programlisting> -$ mono ./example-fanout-Producer.exe [hostname] [portnumber] - </programlisting> - - - <para> - This program has no output; the messages are routed to the - message queue, as prescribed by the binding. - </para> - <para> - 5) Go to the windows where you are running listeners. You should - see the following output for each listener: - </para> - - - <programlisting> -Message: Message 0 -Message: Message 1 -Message: Message 2 -Message: Message 3 -Message: Message 4 -Message: Message 5 -Message: Message 6 -Message: Message 7 -Message: Message 8 -Message: Message 9 -Message: That's all, folks! - </programlisting> - - - <para> - Now we will examine the code for each of these programs. In each - section, we will discuss only - the code that must be added to the skeleton shown in Section - "Creating and Closing Sessions". - </para> - - <!--h3--> - </section> - - <!--h2--> - </section> - - <section role="h2" id="NETUserGuide-ConsumingfromaFanoutExchange"> - <title> - Consuming from a - Fanout Exchange - </title> - - <para> - The first program in the fanout example, Listener.cs, creates a - private queue, binds it to the amq.fanout exchange, and waits for - messages to arrive on the queue, printing them out as they - arrive. It uses a Listener that is identical to the one used in - the direct example: - </para> - - - <programlisting> - public class MessageListener : IMessageListener - { - private readonly ClientSession _session; - private readonly RangeSet _range = new RangeSet(); - public MessageListener(ClientSession session) - { - _session = session; - } - - public void messageTransfer(IMessage m) - { - BinaryReader reader = new BinaryReader(m.Body, Encoding.UTF8); - byte[] body = new byte[m.Body.Length - m.Body.Position]; - reader.Read(body, 0, body.Length); - ASCIIEncoding enc = new ASCIIEncoding(); - string message = enc.GetString(body); - Console.WriteLine("Message: " + message); - // Add this message to the list of message to be acknowledged - _range.add(m.Id); - if (message.Equals("That's all, folks!")) - { - // Acknowledge all the received messages - _session.messageAccept(_range); - lock (_session) - { - Monitor.Pulse(_session); - } - } - } - } - </programlisting> - - - <para> - The listener creates a private queue to receive its messages and - binds it to the fanout exchange: - </para> - - - <programlisting> -string myQueue = session.Name; -session.queueDeclare(myQueue, Option.EXCLUSIVE, Option.AUTO_DELETE); -session.exchangeBind(myQueue, "amq.fanout", "my-key"); - </programlisting> - - - <para> - Now we create a listener and subscribe it to the queue: - </para> - - - <programlisting> -lock (session) -{ - Console.WriteLine("Listening"); - // Create a listener and subscribe it to my queue. - IMessageListener listener = new MessageListener(session); - session.attachMessageListener(listener, myQueue); - session.messageSubscribe(myQueue); - // Receive messages until all messages are received - Monitor.Wait(session); -} - </programlisting> - - - <section role="h3" id="NETUserGuide-PublishingMessagestotheFanoutExchange"> - <title> - Publishing - Messages to the Fanout Exchange - </title> - - <para> - The second program in this example, Producer.cs, writes messages - to the fanout queue. - </para> - - - <programlisting> -// Unlike topic exchanges and direct exchanges, a fanout -// exchange need not set a routing key. -IMessage message = new Message(); -// Asynchronous transfer sends messages as quickly as -// possible without waiting for confirmation. -for (int i = 0; i < 10; i++) -{ - message.clearData(); - message.appendData(Encoding.UTF8.GetBytes("Message " + i)); - session.messageTransfer("amq.fanout", message); -} - -// And send a syncrhonous final message to indicate termination. -message.clearData(); -message.appendData(Encoding.UTF8.GetBytes("That's all, folks!")); -session.messageTransfer("amq.fanout", message); -session.sync(); - </programlisting> - - <!--h3--> - </section> - - <!--h2--> - </section> - - <section role="h2" id="NETUserGuide-WritingPublish-2FSubscribeApplications"> - <title> - Writing - Publish/Subscribe Applications - </title> - - <para> - This section describes two programs that implement - Publish/Subscribe messaging using a topic exchange. - </para> - <para> - • Publisher.cS sends messages to the amq.topic exchange, - using the multipart routing keys usa.news, usa.weather, - europe.news, and europe.weather. - • Listener.cs creates private queues for news, weather, - usa, and europe, binding them to the amq.topic exchange using - bindings that match the corresponding parts of the multipart - routing keys. - </para> - <para> - In this example, the publisher creates messages for topics like - news, weather, and sports that happen in regions like Europe, - Asia, or the United States. A given consumer may be interested in - all weather messages, regardless of region, or it may be - interested in news and weather for the United States, but - uninterested in items for other regions. In this example, each - consumer sets up its own private queues, which receive precisely - the messages that particular consumer is interested in. - </para> - <section role="h3" id="NETUserGuide-RunningthePublishSubscribeExamples"> - <title> - Running - the Publish-Subscribe Examples - </title> - <para> - 1) Make sure your PATH contains the directory - <home>/qpid/lib - </para> - <para> - 2) Make sure that a qpid broker is running: - </para> - - - <programlisting> -$ ps -eaf | grep qpidd - </programlisting> - - - <para> - If a broker is running, you should see the qpidd process in the - output of the above - command. - </para> - <para> - 3) In separate windows, start one or more topic subscribers as - follows: - </para> - - - <programlisting> -$ cd <home>/qpid/examples/direct - </programlisting> - - - <para> - With cygwin: - </para> - - - <programlisting> -$ ./example-pub-sub--Listener.exe [hostname] [portnumber] - </programlisting> - - - <para> - or with mono: - </para> - - - <programlisting> -$ mono ./example-pub-sub-Listener.exe [hostname] [portnumber] - </programlisting> - - - <para> - You will see output similar to this: - </para> - - - <programlisting> -Listening for messages ... -Declaring queue: usa -Declaring queue: europe -Declaring queue: news -Declaring queue: weather - </programlisting> - - - <para> - Each topic consumer creates a set of private queues, and binds - each queue to the amq.topic exchange together with a binding that - indicates which messages should be routed to the queue. - </para> - <para> - 4) In another window, start the topic publisher, which publishes - messages to the amq.topic exchange, as follows: - </para> - - - <programlisting> -$ cd <home>/qpid/examples/direct - </programlisting> - - - <para> - With cygwin: - </para> - - - <programlisting> -$ ./example-pub-sub-Producer.exe [hostname] [portnumber] - </programlisting> - - - <para> - or with mono: - </para> - - - <programlisting> -$ mono ./example-pub-sub-Producer.exe [hostname] [portnumber] - </programlisting> - - - <para> - This program has no output; the messages are routed to the - message queues for each topic_consumer as specified by the - bindings the consumer created. - </para> - <para> - 5) Go back to the window for each topic consumer. You should see - output like this: - </para> - - - <programlisting> -Message: Message 0 from usa -Message: Message 0 from news -Message: Message 0 from weather -Message: Message 1 from usa -Message: Message 1 from news -Message: Message 2 from usa -Message: Message 2 from news -Message: Message 3 from usa -Message: Message 3 from news -Message: Message 4 from usa -Message: Message 4 from news -Message: Message 5 from usa -Message: Message 5 from news -Message: Message 6 from usa -Message: Message 6 from news -Message: Message 7 from usa -Message: Message 7 from news -Message: Message 8 from usa -Message: Message 8 from news -Message: Message 9 from usa -.... -Message: That's all, folks! from weather -Shutting down listener for control -Message: That's all, folks! from europe -Shutting down listener for control - </programlisting> - - - <para> - Now we will examine the code for each of these programs. In each - section, we will discuss only - the code that must be added to the skeleton shown in Section - "Creating and Closing Sessions". - </para> - <!--h3--> - </section> - - - <section role="h3" id="NETUserGuide-PublishingMessagestoaTopicExchange"> - <title> - Publishing - Messages to a Topic Exchange - </title> - - <para> - The first program in the publish/subscribe example, Publisher.cs, - defines two new functions: one that publishes messages to the - topic exchange, and one that indicates that no more messages are - coming. - </para> - <para> - The publishMessages function publishes a series of five messages - using the specified routing key. - </para> - - - <programlisting> -private static void publishMessages(ClientSession session, string routing_key) -{ - IMessage message = new Message(); - // Asynchronous transfer sends messages as quickly as - // possible without waiting for confirmation. - for (int i = 0; i < 10; i++) - { - message.clearData(); - message.appendData(Encoding.UTF8.GetBytes("Message " + i)); - session.messageTransfer("amq.topic", routing_key, message); - } -} - </programlisting> - - - <para> - The noMoreMessages function signals the end of messages using the - control routing key, which is reserved for control messages. - </para> - - - <programlisting> -private static void noMoreMessages(ClientSession session) -{ - IMessage message = new Message(); - // And send a syncrhonous final message to indicate termination. - message.clearData(); - message.appendData(Encoding.UTF8.GetBytes("That's all, folks!")); - session.messageTransfer("amq.topic", "control", message); - session.sync(); -} - </programlisting> - - - <para> - In the main body of the program, messages are published using - four different routing keys, and then the end of messages is - indicated by a message sent to a separate routing key. - </para> - - - <programlisting> -publishMessages(session, "usa.news"); -publishMessages(session, "usa.weather"); -publishMessages(session, "europe.news"); -publishMessages(session, "europe.weather"); - -noMoreMessages(session); - </programlisting> - <!--h3--> - </section> - - <section role="h3" id="NETUserGuide-ReadingMessagesfromtheQueue2"> - <title> - Reading - Messages from the Queue - </title> - - <para> - The second program in the publish/subscribe example, Listener.cs, - creates a local private queue, with a unique name, for each of - the four binding keys it specifies: usa.#, europe.#, #.news, and - #.weather, and creates a listener. - </para> - - - <programlisting> -Console.WriteLine("Listening for messages ..."); -// Create a listener -prepareQueue("usa", "usa.#", session); -prepareQueue("europe", "europe.#", session); -prepareQueue("news", "#.news", session); -prepareQueue("weather", "#.weather", session); - </programlisting> - - - <para> - The prepareQueue() method creates a queue using a queue name and - a routing key supplied as arguments it then attaches a listener - with the session for the created queue and subscribe for this - receiving messages from the queue: - </para> - - - <programlisting> -// Create a unique queue name for this consumer by concatenating -// the queue name parameter with the Session ID. -Console.WriteLine("Declaring queue: " + queue); -session.queueDeclare(queue, Option.EXCLUSIVE, Option.AUTO_DELETE); - -// Route messages to the new queue if they match the routing key. -// Also route any messages to with the "control" routing key to -// this queue so we know when it's time to stop. A publisher sends -// a message with the content "That's all, Folks!", using the -// "control" routing key, when it is finished. - -session.exchangeBind(queue, "amq.topic", routing_key); -session.exchangeBind(queue, "amq.topic", "control"); - -// subscribe the listener to the queue -IMessageListener listener = new MessageListener(session); -session.attachMessageListener(listener, queue); -session.messageSubscribe(queue); - </programlisting> - <!--h3--> - </section> - <!--h2--> - </section> - - <section role="h2" id="NETUserGuide-WritingRequest-2FResponseApplications"> - <title> - Writing - Request/Response Applications - </title> - - <para> - In the request/response examples, we write a server that accepts - strings from clients and converts them to upper case, sending the - result back to the requesting client. This example consists of - two programs. - </para> - <itemizedlist> - <listitem> - <para>Client.cs is a client application that sends messages to the - server. - • Server.cs is a service that accepts messages, converts - their content to upper case, and sends the result to the - amq.direct exchange, using the request's reply-to property as - the routing key for the response. - </para> - </listitem> - </itemizedlist> - <section role="h3" id="NETUserGuide-RunningtheRequest-2FResponseExamples"> - <title> - Running - the Request/Response Examples - </title> - <para> - 1) Make sure your PATH contains the directory - <home>/qpid/lib - </para> - <para> - 2) Make sure that a qpid broker is running: - </para> - - - <programlisting> -$ ps -eaf | grep qpidd - </programlisting> - - - <para> - If a broker is running, you should see the qpidd process in the - output of the above - command. - </para> - <para> - 3) Run the server. - </para> - <para> - $ cd <home>/qpid/examples/direct - </para> - - - <programlisting> - With cygwin: - </programlisting> - - - <para> - $ ./example-request-response-Server.exe [hostname] [portnumber] - </para> - - - <programlisting> - or with mono: - </programlisting> - - - <para> - $ mono ./example-request-response-Server.exe [hostname] [portnumber] - </para> - - - <programlisting> - You will see output similar to this: - </programlisting> - - - <para> - Waiting for requests - </para> - - - <programlisting> -4) In a separate window, start a client: - -$ cd <home>/qpid/examples/direct - </programlisting> - - - <para> - With cygwin: - </para> - - - <programlisting> -$ ./example-request-response-Client.exe [hostname] [portnumber] - </programlisting> - - - <para> - or with mono: - </para> - - - <programlisting> -$ mono ./example-request-response-Client.exe [hostname] [portnumber] - </programlisting> - - - <para> - You will see output similar to this: - </para> - - - <programlisting> -Activating response queue listener for: clientSystem.Byte[] -Waiting for all responses to arrive ... -Response: TWAS BRILLIG, AND THE SLITHY TOVES -Response: DID GIRE AND GYMBLE IN THE WABE. -Response: ALL MIMSY WERE THE BOROGROVES, -Response: AND THE MOME RATHS OUTGRABE. -Shutting down listener for clientSystem.Byte[] -Response: THAT'S ALL, FOLKS! - </programlisting> - - - <para> - 4) Go back to the server window, the output should be similar to - this: - </para> - - - <programlisting> -Waiting for requests -Request: Twas brillig, and the slithy toves -Request: Did gire and gymble in the wabe. -Request: All mimsy were the borogroves, -Request: And the mome raths outgrabe. -Request: That's all, folks! - </programlisting> - - - <para> - Now we will examine the code for each of these programs. In each - section, we will discuss only the code that must be added to the - skeleton shown in Section "Creating and Closing Sessions". - </para> - <!--h3--> - </section> - - - <section role="h3" id="NETUserGuide-TheClientApplication"> - <title> - The Client - Application - </title> - - <para> - The first program in the request-response example, Client.cs, - sets up a private response queue to receive responses from the - server, then sends messages the server, listening to the response - queue for the server's responses. - </para> - - - <programlisting> -string response_queue = "client" + session.getName(); -// Use the name of the response queue as the routing key -session.queueDeclare(response_queue); -session.exchangeBind(response_queue, "amq.direct", response_queue); - -// Create a listener for the response queue and listen for response messages. -Console.WriteLine("Activating response queue listener for: " + response_queue); -IMessageListener listener = new ClientMessageListener(session); -session.attachMessageListener(listener, response_queue); -session.messageSubscribe(response_queue); - </programlisting> - - - <para> - Set some properties that will be used for all requests. The - routing key for a request is request. - The reply-to property is set to the routing key for the client's - private queue. - </para> - - - <programlisting> -IMessage request = new Message(); -request.DeliveryProperties.setRoutingKey("request"); -request.MessageProperties.setReplyTo(new ReplyTo("amq.direct", response_queue)); - </programlisting> - - - <para> - Now send some requests... - </para> - - - <programlisting> -string[] strs = { - "Twas brillig, and the slithy toves", - "Did gire and gymble in the wabe.", - "All mimsy were the borogroves,", - "And the mome raths outgrabe.", - "That's all, folks!" - }; -foreach (string s in strs) -{ - request.clearData(); - request.appendData(Encoding.UTF8.GetBytes(s)); - session.messageTransfer("amq.direct", request); -} - </programlisting> - - - <para> - And wait for responses to arrive: - </para> - - - <programlisting> -Console.WriteLine("Waiting for all responses to arrive ..."); -Monitor.Wait(session); - </programlisting> - <!--h3--> - </section> - - <section role="h3" id="NETUserGuide-TheServerApplication"> - <title> - The Server - Application - </title> - - <para> - The second program in the request-response example, Server.cs, - uses the reply-to property as the routing key for responses. - </para> - <para> - The main body of Server.cs creates an exclusive queue for - requests, then waits for messages to arrive. - </para> - - - <programlisting> -const string request_queue = "request"; -// Use the name of the request queue as the routing key -session.queueDeclare(request_queue); -session.exchangeBind(request_queue, "amq.direct", request_queue); - -lock (session) -{ - // Create a listener and subscribe it to the request_queue - IMessageListener listener = new MessageListener(session); - session.attachMessageListener(listener, request_queue); - session.messageSubscribe(request_queue); - // Receive messages until all messages are received - Console.WriteLine("Waiting for requests"); - Monitor.Wait(session); -} - </programlisting> - - - <para> - The listener's messageTransfer() method converts the request's - content to upper case, then sends a response to the broker, using - the request's reply-to property as the routing key for the - response. - </para> - - - <programlisting> -BinaryReader reader = new BinaryReader(request.Body, Encoding.UTF8); -byte[] body = new byte[request.Body.Length - request.Body.Position]; -reader.Read(body, 0, body.Length); -ASCIIEncoding enc = new ASCIIEncoding(); -string message = enc.GetString(body); -Console.WriteLine("Request: " + message); - -// Transform message content to upper case -string responseBody = message.ToUpper(); - -// Send it back to the user -response.clearData(); -response.appendData(Encoding.UTF8.GetBytes(responseBody)); -_session.messageTransfer("amq.direct", routingKey, response); - </programlisting> - - <!--h3--> - </section> - <!--h2--> - </section> - <!--h1--> - </section> - - - </section> |
