用本地C#写出的WebService利用MQTT协议去连接阿里云来实现数值的远程传输和使用(异步调用)第一篇:用委托的方式去异步调用

WebService的建立

  首先,我们需要建立一个本地用C#创建出来的WebService,这里与我之前写的一篇同步调用的文章里的内容是一样的,所以就不再在这里进行过多描述了,可以去我之前的一篇文章里查看相关的建立方法: https://blog.csdn.net/qq_19408097/article/details/97029286 ,创建Webservice的内容一直到我原来文章的“这段代码的大致解读”为止,之前的都是一样的,从那里之后,我们的内容才会有变化,因为我现在的代码是才用的异步调用的方法。
  然后我们将新的代码复制进去:

using System;
using System.Net;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using uPLibrary.Networking.M2Mqtt;//如果出现报错,说明MQTT库没有装
using uPLibrary.Networking.M2Mqtt.Messages;//如果出现报错,说明MQTT库没有装
using System.Security.Cryptography;
using System.Web;
using System.Web.Services;
using System.Threading;
using shuju;
namespace web
{
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    public class web : System.Web.Services.WebService
    {
        //阿里云的数据
        static string ProductKey = "***";//写入自己设备的参数
        static string DeviceName = "***";//写入自己设备的参数
        static string DeviceSecret = "***";//写入自己设备的参数
        static string RegionId = "***";//写入自己设备的参数
        static string PubTopic = "/" + ProductKey + "/" + DeviceName + "/user/update";
        static string SubTopic = "/" + ProductKey + "/" + DeviceName + "/user/get";

        //声明一个委托
        delegate string LongCalculationDelegate(int a);
        [WebMethod(Description = "阿里云")]
        public void (int a)//主程序
        {
            //事件的注册
            LongCalculationDelegate LongCalcDelegate = new LongCalculationDelegate(xiancheng);
            AsyncCallback callback = new AsyncCallback(CallbackMethod);
            //调用BeginInvoke函数开始异步调用
            LongCalcDelegate.BeginInvoke(a, callback, LongCalcDelegate);
        }
        static void Client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)//将读取到的数据存到common里面去
        {
            // 处理读取到的信息
            string topic = e.Topic;
            string message = Encoding.ASCII.GetString(e.Message);
            common.Name = message;
        }
        static string xiancheng(int a)//返回读取到的数据
        {
            //开始连接阿里云
            IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
            string clientId = host.AddressList.FirstOrDefault(
                ip => ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).ToString();
            string t = Convert.ToString(DateTimeOffset.Now.ToUnixTimeMilliseconds());
            string signmethod = "hmacmd5";
            Dictionary<string, string> dict = new Dictionary<string, string>();
            dict.Add("productKey", ProductKey);
            dict.Add("deviceName", DeviceName);
            dict.Add("clientId", clientId);
            dict.Add("timestamp", t);
            string mqttUserName = DeviceName + "&" + ProductKey;
            string mqttPassword = IotSignUtils.sign(dict, DeviceSecret, signmethod);
            string mqttClientId = clientId + "|securemode=3,signmethod=" + signmethod + ",timestamp=" + t + "|";
            string targetServer = ProductKey + ".iot-as-mqtt." + RegionId + ".aliyuncs.com";
            MqttClient client = new MqttClient(targetServer);
            client.ProtocolVersion = MqttProtocolVersion.Version_3_1_1;
            client.Connect(mqttClientId, mqttUserName, mqttPassword, false, 60);
            client.MqttMsgPublishReceived += Client_MqttMsgPublishReceived;
            //发布消息
            String content = Convert.ToString(a);
            //将string类转换成byte[]
            byte[] by1 = System.Text.Encoding.ASCII.GetBytes(content);
            var id = client.Publish(PubTopic, by1);
            //订阅消息
            var id2 = client.Subscribe(new string[] { SubTopic }, new byte[] { 0 });

        lop: //子线程里一直等待他的数据回来
            if (string.Compare(common.Name, " ") == 0)
                goto lop;
            else
            {
            loop:
                if (string.Compare(common.Name, Convert.ToString(a)) != 0)
                    goto loop;
                else
                    return common.Name;
            }
        }
        static void CallbackMethod(IAsyncResult ar)//回调方法
        {
            LongCalculationDelegate dlgt = (LongCalculationDelegate)ar.AsyncState;
            string results = dlgt.EndInvoke(ar);
            common.Name = results;
        }

    }
    public class IotSignUtils//IoT平台接入password签名算法
    {
        public static string sign(Dictionary<string, string> param,
                            string deviceSecret, string signMethod)
        {
            string[] sortedKey = param.Keys.ToArray();
            Array.Sort(sortedKey);
            StringBuilder builder = new StringBuilder();
            foreach (var i in sortedKey)
            {
                builder.Append(i).Append(param[i]);
            }

            byte[] key = Encoding.UTF8.GetBytes(deviceSecret);
            byte[] signContent = Encoding.UTF8.GetBytes(builder.ToString());
            var hmac = new HMACMD5(key);
            byte[] hashBytes = hmac.ComputeHash(signContent);

            StringBuilder signBuilder = new StringBuilder();
            foreach (byte b in hashBytes)
                signBuilder.AppendFormat("{0:x2}", b);
            return signBuilder.ToString();
        }
    }
}

  这里我采用的方法是阻塞了子线程,但是这并不会影响到主线程的运行,所以我觉得问题应该不大。我将需要等待阿里云回复的那一部分做成了委托的形式,然后进行委托的异步调用,这样就不会出现调用WebService的时候出现占线的问题了。
  但是现在代码就目前为止还是会报错的,因为我们还没有写 “shuju” 这个类。
  按下ctrl+shift+A进行页面的添加。选择如下该项:(此处与我原来那篇内容一致,所所以图片我就直接复制过来了)
在这里插入图片描述
建立完成以后,将下列代码拷入:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace shuju
{
    public static class common // static 不是必须
    {
        private static string name = " ";
        public static string Name
        {
            get { return name; }
            set { name = value; }
        }
    }
}

  然后这个程序就没有问题了。运行一下就可以看到如图:在这里插入图片描述
然后我们点击 “值” 这个按钮,输入数值以后点击调用:
在这里插入图片描述
然后我们前往阿里云查看数据,发现数据记录已经保存到了阿里云里的日志服务里面:
在这里插入图片描述
点击MessageID后,发现数值一致:
在这里插入图片描述

Web Service的发布

  这一部分与我之前写过的同步调用里面的发布方法是一致的,可以前往 https://blog.csdn.net/qq_19408097/article/details/97108147 这个网址进行查看,我就不在这里进行重复的叙述了。

如何引用Web Service?

  关于这个问题我在下下篇文章中进行详细的教程。

总结

  这样的一个WebService就比我之前写的同步调用的要有用得多,因为他不会出现占线的问题,所以,所以在应用方面的效果会比之前的更加好一些,接下来的一篇我会用另一种Task的异步调用的方法去写,为什么要用Task呢?因为Task的普适性更高,而且提供了更多的API可以使用,用起来功能更强,比起用委托的方法,我更建议用Task的方法去写,因为Task可以用它里面的ContinueWith函数对子线程得到的结果进行处理,这一点是委托所做不到的,所以我建议还是用Task方法,虽然委托的方法显然要更加简单一点,但是实用性我个人认为是不如Task的。

发布了40 篇原创文章 · 获赞 80 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_19408097/article/details/97134747