This article describes how to use the AMQP SDK for .NET to connect a client to Alibaba Cloud IoT Platform and receive messages from IoT Platform.

Development environment

The following table describes the development environment.

Framework Supported version
.Net Framework 3.5, 4.0, 4.5, and later
.NET Micro Framework 4.2 or later
.NET nanoFramework 1.0 or later
.NET Compact Framework 3.9 or later
.Net Core on Windows 10 and Ubuntu 14.04 1.0 or later
Mono 4.2.1 or later

Download SDK for .Net

We recommend that you use the AMQP.Net Lite library. To download the library and view its instructions, see AMQP.Net Lite.

Add a dependency

Add the following dependency to the packages.config file:

<packages>
  <package id="AMQPNetLite" version="2.2.0" targetFramework="net47" />
</packages>

Sample code

For more information about the parameters in the following sample code, see Connect an AMQP client to IoT Platform.

using System;
using System.Text;
using Amqp;
using Amqp.Sasl;
using Amqp.Framing;
using System.Threading;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Security.Cryptography;

namespace amqp
{
    class MainClass
    {
        // The endpoint. For more information, see Connect an AMQP client to IoT Platform.
        static string Host = "${YourHost}";
        static int Port = 5671;
        static string AccessKey = "${YourAccessKey}";
        static string AccessSecret = "${YourAccessSecret}";
        static string consumerGroupId = "${YourConsumerGroupId}";
        static string clientId = "${YourClientId}";
        // iotInstanceId: If you use a purchased instance, you must specify the instance ID. If you use a public instance, you can enter an empty string ("").
        static string iotInstanceId = "${YourIotInstanceId}"; 
        static int Count = 0;
        static int IntervalTime = 10000;

        static Address address;

        public static void Main(string[] args)
        {
            long timestamp = GetCurrentMilliseconds();
            string param = "authId=" + AccessKey + "&timestamp=" + timestamp;
            // The structure of the userName parameter. For more information, see Connect an AMQP client to IoT Platform.
            string userName = clientId + "|authMode=aksign,signMethod=hmacmd5,consumerGroupId=" + consumerGroupId
               + ",iotInstanceId=" + iotInstanceId + ",authId=" + AccessKey + ",timestamp=" + timestamp + "|";
            // The structure of the signature and the password parameters. For more information, see Connect an AMQP client to IoT Platform.
            string password = doSign(param, AccessSecret, "HmacMD5");

            DoConnectAmqp(userName, password);

            ManualResetEvent resetEvent = new ManualResetEvent(false);
            resetEvent.WaitOne();
        }

        static void DoConnectAmqp(string userName, string password)
        {
            address = new Address(Host, Port, userName, password);
            // Creates a connection.
            ConnectionFactory cf = new ConnectionFactory();
            // Uses a local TSL certificate if required.
            //cf.SSL.ClientCertificates.Add(GetCert());
            //cf.SSL.RemoteCertificateValidationCallback = ValidateServerCertificate;
            cf.SASL.Profile = SaslProfile.External;
            cf.AMQP.IdleTimeout = 120000;
            // Specifies the required values for the cf.AMQP.ContainerId and cf.AMQP.HostName parameters.
            cf.AMQP.ContainerId = "client.1.2"; 
            cf.AMQP.HostName = "contoso.com";
            cf.AMQP.MaxFrameSize = 8 * 1024;
            var connection = cf.CreateAsync(address).Result;

            // The connection exception feature is disabled.
            connection.AddClosedCallback(ConnClosed);

            // Receives messages.
            DoReceive(connection);
        }

        static void DoReceive(Connection connection)
        {
            // Creates a session.
            var session = new Session(connection);

            // Creates a receiver. The receiver is used to connect to IoT Platform and receive messages.
            var receiver = new ReceiverLink(session, "queueName", null);


            receiver.Start(20, (link, message) =>
            {
                object messageId = message.ApplicationProperties["messageId"];
                object topic = message.ApplicationProperties["topic"];
                string body = Encoding.UTF8.GetString((Byte[])message.Body);
                // Note: Do not implement a time-consuming logic for this scenario. If you need to implement a business process, use a new thread. Otherwise, message consumption may be blocked. The slower the speed at which messages are consumed, the higher the possibility that more message are sent again.
                Console.WriteLine("receive message, topic=" + topic + ", messageId=" + messageId + ", body=" + body);

                // An ACK message.
                link.Accept(message);
            });


        }

        // If an exception occurs, the client attempts to re-connect to IoT Platform.
        // This is a simple example. You can use an exponential backoff algorithm to improve the exception handling mechanism and the reconnection policy.
        static void ConnClosed(IAmqpObject _, Error e)
        {
            Console.WriteLine("ocurr error: " + e);
            if(Count < 3)
            {
                Count += 1;
                Thread.Sleep(IntervalTime * Count);
            }
            else
            {
                Thread.Sleep(120000);
            }

            // Re-establishes the connection.
            DoConnectAmqp(address.User, address.Password);
        }

        static X509Certificate GetCert()
        {
            string certPath = Environment.CurrentDirectory + "/root.crt";
            X509Certificate crt = new X509Certificate(certPath);

            return crt;
        }

        static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }

        static long GetCurrentMilliseconds()
        {
            DateTime dt1970 = new DateTime(1970, 1, 1);
            DateTime current = DateTime.Now;
            return (long)(current - dt1970).TotalMilliseconds;
        }

        // The signature algorithm. Valid values: hmacmd5, hmacsha1, and hmacsha256.
        static string doSign(string param, string accessSecret, string signMethod)
        {
            //signMethod = HmacMD5
            byte[] key = Encoding.UTF8.GetBytes(accessSecret);
            byte[] signContent = Encoding.UTF8.GetBytes(param);
            var hmac = new HMACMD5(key);
            byte[] hashBytes = hmac.ComputeHash(signContent);
            return Convert.ToBase64String(hashBytes);
        }
    }
}