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的。