3. Your First AMPS Program

In this chapter, we will learn more about the structure and features of the AMPS C# library, and build our first C# program using AMPS.

About the Client Library

The AMPS client is packaged as a single managed assembly, AMPS.Client.dll You can find AMPS.Client.dll in the AMPS/bin directory of your AMPS C# client. Every .NET application you build will need to reference this assembly file, and the assembly must be deployed along with your application in order for your application to function properly.

Connecting to AMPS

Let’s begin by writing a simple program that connects to an AMPS server and publishes a single message to a topic:

using System;
using AMPS.Client;
using AMPS.Client.Exceptions;

namespace AMPSBookExamples
{
    class ConnectToAMPS
    {
        static void Main(string[] args)
        {
            using(Client client = new Client("exampleClient"))
            {
                try
                {
                    client.connect("tcp://192.168.1.3:9007/amps");
                    client.logon();
                    client.publish("messages", @"{ ""message"" : ""Hello, World!"" }");
                }
                catch (AMPSException e)
                {
                    Console.Error.WriteLine(e);
                }
            }
        }
    }
}

Example 3.1: Connecting to AMPS

In the preceding Example 3.1, we show the entire program; but future examples will isolate one or more specific portions of the code. The next section describes how to build and run the application and explains the code in further detail.

Build and Run

To build this program, create a new C# command-line project in Visual Studio and add a reference to AMPS.Client.dll using the “Add Reference...”’ option in Visual Studio. Replace the code in Program.cs with the code in Example 3.1, and then modify the client.connect() on line 14 with the address and port of your AMPS server. Now, you should be able to compile and execute the code, and if the AMPS server is running, the message Hello world is published to the messages topic. If an error occurs, an exception will be written to the console.

If the message is published successfully, there is no output to the console. We will demonstrate how to create a subscriber to receive messages in Chapter 4.

Examining the Code

Let us now revisit the code we listed earlier.

using System;
using AMPS.Client;
using AMPS.Client.Exceptions;

namespace AMPSBookExamples
{
    class ConnectToAMPS
    {
        static void Main(string[] args)
        {

            // This line creates a new Client object. Client encapsulates a single connection
            // to an AMPS server. Methods on Client allow for connecting, disconnecting,
            // publishing, and subscribing to an AMPS server. The argument to the Client
            // constructor, "exampleClient", is a name chosen by the client to identify itself
            // to the server. Errors relating to this connection will be logged with reference
            // to this name, and AMPS uses this name to help detect duplicate messages. AMPS
            // enforces uniqueness for client names when a transaction log is configured, and
            // it is good practice to always use unique client names. The using statement ensures
            // that the connection underlying the client is disposed of before the program exists.
            // Client implements the .NET IDisposable interface, making it easy to ensure that
            // are freed when your Client is no longer in use. There is no need to
            // disconnect the Client when it is protected by a using statement.
            using(Client client = new Client("exampleClient"))
            {

                try
                {

                // At this point, we have a valid AMPS connection and can begin to use it to
                // publish and subscribe to messages.
                client.connect("tcp://192.168.1.3:9007/amps");

                client.logon()

                // Here, we publish a single message to AMPS on the messages topic, containing the
                // data { "message" : "Hello, world!" }.
                // This JSON message is sent to the server. Upon successful completion of this function,
                // the AMPS client has sent the message to the server, and subscribers to the messages
                // topic will receive this message.
                client.publish("messages", @"{ ""message"" : ""Hello, World!"" }");
                }

                catch (AMPSException e)
                {
                    Console.Error.WriteLine(e);
                }
            }
        }
    }
}

Client Names

AMPS uses the name of the client as a session identifier and as part of the identifier for a message. For this reason, when a transaction log is enabled in the AMPS instance (that is, when the instance is recording a sequence of publishes and attempting to eliminate duplicate publishes), an AMPS instance will only allow one application with a given client name to connect to the instance.

When a transaction log is present, AMPS requires the Client Name for a publisher to be:

  • Unique within a set of replicated AMPS instances
  • Consistent from invocation to invocation if the publisher will be publishing tthe same logical stream of messages

60East recommends always using consistent, unique client names. For example, the client name could be formed by combining the application name, an identifier for the host system, and the id of the user running the application. A strategy like this provides a name that will be different for different users or on different systems, but consistent for instances of the application that should be treated as equivalent to the AMPS system.

Connection Strings

The AMPS clients use connection strings to determine the server, port, transport, and protocol to use to connect to AMPS. When the connection point in AMPS accepts multiple message types, the connection string also specifies the precise message type to use for this connection. Connection strings have a number of elements.

elements of a connection string

Figure 3.1: elements of a connection string

As shown in the figure above, connection strings have the following elements:

  • Transport defines the network used to send and receive messages from AMPS. In this case, the transport is tcp. For connections to transports that use the Secure Sockets Layer (SSL), use tcps.

  • Host address defines the destination on the network where the AMPS instance receives messages. The format of the address is dependent on the transport. For tcp and tcps, the address consists of a host name and port number. In this case, the host address is localhost:9007.

  • Protocol sets the format in which AMPS receives commands from the client. Most code uses the default amps protocol, which sends header information in JSON format. AMPS supports the ability to develop custom protocols as extension modules, and AMPS also supports legacy protocols for backward compatibility.

  • MessageType specifies the message type that this connection uses. This component of the connection string is required if the protocol accepts multiple message types and the transport is configured to accept multiple message types. If the protocol does not accept multiple message types, this component of the connection string is optional, and defaults to the message type specified in the transport.

    Legacy protocols such as fix, nvfix and xml only accept a single message type, and therefore do not require or accept a message type in the connection string.

As an example, a connection string such as

tcp://localhost:9007/amps/json

would work for programs connecting from the local host to a Transport configured as follows:

<AMPSConfig>
    ...

    <!-- This transport accepts any known message type for the instance: the
         client must specify the message type. -->
    <Transport>
        <Name>any-tcp</Name>
        <Type>tcp</Type>
        <InetAddr>9007</InetAddr>
        <Protocol>amps</Protocol>
    </Transport>

    ...
</AMPSConfig>

See the AMPS Configuration Guide for more information on configuring transports.

Providing Credentials in a Connection String

When using the default authenticator, the AMPS clients support the standard format for including a username and password in a URI, as shown below:

tcp://user:password@host:port/protocol/message_type

When provided in this form, the default authenticator provides the username and password specified in the URI. If you have implemented another authenticator, that authenticator controls how passwords are provided to the AMPS server.

Connection Parameters

When specifying a URI for connection to an AMPS server, you may specify a number of transport-specific options in the parameters section of the URIconnection parameters. Here is an example:

tcp://localhost:9007/amps/json?tcp_nodelay=true&tcp_sndbuf=100000

In this example, we have specified the AMPS instance on localhost, port 9007, connecting to a transport that uses the amps protocol and sending JSON messages. We have also set two parameters, tcp_nodelay tcp_nodelay, a Boolean (true/false) parameter, and tcp_sndbuf tcp_sndbuf, an integer parameter. Multiple parameters may be combined to finely tune settings available on the transport. Normally, you’ll want to stick with the defaults on your platform, but there may be some cases where experimentation and fine-tuning will yield higher or more efficient performance.

AMPS supports the value of tcp in the connection string for TCP/IP connections, and the value of tcps in the connection string for SSL encrypted connections.

Transport options

The following transport options are available for TCP connections:

bind (ip address) Sets the interface to bind the outgoing socket to.
tcp_rcvbuf (integer) Sets the socket receive buffer size. This defaults to the system default size. (On Linux, you can find the system default size in /proc/sys/net/core/rmem_default.)
tcp_sndbuf (integer) Sets the socket send buffer size. This defaults to the system default size. (On Linux, you can find the system default size in /proc/sys/net/core/wmem_default.)
tcp_nodelay (boolean) Enables or disables the TCP_NODELAY setting on the socket. By default TCP_NODELAY is disabled.
tcp_linger (integer) Enables and sets the SO_LINGER value for the socket. By default, SO_LINGER is enabled with a value of 10, which specifies that the socket will linger for 10 seconds.
tcp_keepalive (boolean) . Enables or disables the SO_KEEPALIVE value for the socket. The default value for this option is true.

AMPS additional logon options

The connection string can also be used to pass logon parameters to AMPS. AMPS supports the following additional logon option:

pretty Provide formatted representations of binary messages rather than the original message contents.

Next Steps

Once your application is built, you will need to think about how to deploy it to additional computers. With your application’s dependency on AMPS.Client.dll, you need to include AMPS.Client.dll along with your application. The most straightforward way to accomplish this is to install AMPS.Client.dll into the same folder as your .exe file. For example, if you distribute your executable in a zip file that users are expected to unpack, simply include AMPS.Client.dll assemblies into that zip file. When your executable runs, Windows will attempt to load AMPS.Client.dll from the same directory as your executable, and if it is not found, your executable will fail to run.

If your organization develops and deploys many AMPS applications and would like more centralized control over the maintenance of these AMPS client deployments, consider installing AMPS.Client.dll into the Global Assembly Cache (“GAC”). The GAC allows you to share one copy of an assembly — like the AMPS client — across many applications on a computer. This technique requires that the assembly have a strong name, and that you use an installer that places AMPS.Client.dll into the GAC. Installing the assembly in the GAC is not recommended unless many applications will share an AMPS client. For more information on the GAC, visit the Microsoft Developer Network documentation on the GAC at http://msdn.microsoft.com/en-us/library/yf1d93sz.aspx.

You are now able to develop and deploy an application in C# that publishes messages to AMPS. In the following chapters, you will learn how to subscribe to messages, use content filters, work with SOW caches, and fine-tune messages that you send.