分类 .net 下的文章

MQTTnet4入门(二)实现客户端


上一篇写服务端的文章已经是去年年底,现在MQTTnet的版本是4.2.1.781,总的来说改动不大。下面以新版为例实现一个客户端。

var mqttClientOptions = new MqttClientOptionsBuilder()
            .WithTcpServer("地址", 端口)
            .WithClientId("我是客户端名称")//连接id
            .WithCredentials("demo","123456")//如果有用户名密码
            .WithTls()//如果启用了ssl/tls
            .WithProtocolVersion(MqttProtocolVersion.V500)//如果用mqtt5
            .Build();//配置
        IMqttClient client = new MqttFactory().CreateMqttClient();//创建连接
        client.ApplicationMessageReceivedAsync += MqttClient_ApplicationMessageReceivedAsync;//收到消息的方法
        client.ConnectedAsync += Client_ConnectedAsync;//连接成功的方法
        client.ConnectingAsync += Client_ConnectingAsync;//连接中的方法

配置里面一个大坑害我调了一个小时,如果mqtt服务端需要用户名和密码,那么使用.WithCredentials()来填写。我一直以为是.WithUserProperty(),极有迷惑性。

连接并订阅主题

// User proper cancellation and no while(true).
                while (true)
                {
                    try
                    {
                        // This code will also do the very first connect! So no call to _ConnectAsync_ is required in the first place.
                        if (!await client.TryPingAsync())
                        {
                            var response= await client.ConnectAsync(mqttClientOptions, CancellationToken.None);
                            DelegateSetRtbText(response.ReasonString);
                            // Subscribe to topics when session is clean etc.
                            var mqttSubscribeOptions = new MqttFactory().CreateSubscribeOptionsBuilder()
                            .WithTopicFilter(
                                f =>
                                {
                                    f.WithTopic("shi");//订阅主题
                                })
                            .Build();
                            await client.SubscribeAsync(mqttSubscribeOptions);
                        }
                    }
                    catch
                    {
                        // Handle the exception properly (logging etc.).
                    }
                    finally
                    {
                        // Check the connection state every 5 seconds and perform a reconnect if required.
                        await Task.Delay(TimeSpan.FromSeconds(5));
                    }
                }

好了,就这么简单


FBrowserCEF3 C#版的一些问题


最近在精益论坛上看到有个叫FBro浏览器库,是对CEF3的一个封装。除了易语言模块,还提供了C#版,正好有个网页填表在selenium和cef下都被反爬策略识别了,所以试了下这个模块,碰到并解决了一些问题,供大家借鉴。

一、只支持64位

这个模块只支持64位编译,所以32位的操作系统是没法使用的。这也是我最终放弃的原因,公司的公用电脑是32位的win7,重装系统不现实。

二、nuget包安装及编译

这个提供了nuget包,直接在nuget管理器里搜索就有了。
nuget.png

需要把FBroSharp.x64和FBroSharp.Common.x64两个包都装上。我在生成的时候碰到了下图的错误:
fault.png
这是由于本身不支持32位,VS默认目标平台是Any CPU,所以只要在点击项目——属性——生成,将平台由Any CPU改成x64即可。
shuxing.png
粗略看了下文档,封装的还是挺不错的,比直接用cefsharp简单点。可惜不符合我的要求,继续鼓捣webview2去了。


MQTTnet4入门(一)实现服务端


MQTT主要用于物联网,最近因为一些特殊需求,需要做个类似SCADA的东西,经过评估MQTT比较符合预期。
对于MQTT,.Net下有个使用最广泛的库MQTTnet,nuget里最新的版本是4.1.4.563。网上搜了一下,现有教程基本都是2或者3这些版本,而到了4.0版里面的使用发放确实不太一样,所以本篇以上述版本为例,实现一个简单的服务端和客户端。

创建服务端:

MqttServer server;

var optionbuilder = new MqttServerOptionsBuilder()
            .WithDefaultEndpoint()//设置默认地址127.0.0.1
            .WithDefaultEndpointPort(1883);//设置端口

server = new MqttFactory().CreateMqttServer(optionbuilder.Build());//创建服务端实例
server.ClientConnectedAsync += Server_ClientConnectedAsync;//实现客户端连接方法
server.StartAsync();//启动服务端

对于其中的客户端连接后的方法:

private Task Server_ClientConnectedAsync(ClientConnectedEventArgs arg)
{
    MessageBox.Show($"{arg.ClientId}上线了!");
    return Task.CompletedTask;
}

一般情况下,服务端(broker)只是一个中转站,所有的消息都是由客户端发送至服务端,然后服务端转发至其他客户端。但服务端也提供了一个方法,可以实现服务端向客户端进行广播:

server.InjectApplicationMessage(
            new InjectedMqttApplicationMessage(
                new MqttApplicationMessageBuilder()
                .WithTopic("主题")
                .WithPayload("消息内容")
                .Build()
                )
            );

HttpRequest在执行ReadToEnd()时卡住


最近在请求内网MIS系统的某一接口时,发现请求超时了。一开始以为网络卡,延长请求超时时间到1分钟,依然超时。

加断点调试,发现请求Requeset请求一直卡在ReadToEnd()

using (Stream streamReceive = response.GetResponseStream())
 {
    using (StreamReader streamReader = new StreamReader(streamReceive, encoding))
    {
        string strResult = streamReader.ReadToEnd();
        try
        {
            return strResult;
        }
        catch (Exception ex)
        {
            return ex.Message;
        }
     }
  }

查询了一下,发现原因出在了HTTP协议的版本上。

内网MIS服务器的HTTP版本是1.1,发送request后,response不会断开,所以ReadToEnd()就会读不完数据,造成一直卡在这里。

所以解决办法有两个:
1.设置request的http版本为1.0

request.ProtocolVersion=HttpVersion.Version10;

2.不使用ReadToEnd(),而是根据response里和content_length长度来决定需要读多少字节。读到够数就立刻关闭。


OneDrive无法登录 0x8004de88


最近几天发现笔记本电脑上的onedrive离线了,一直提示我登录,点击登录直接报代码0x8004de88。
按照网上的解决方案,把OneDrive卸载重装也没用,连了梯子也没用,但网页版是能够正常登录的。
后来下了个所谓“延期圈”的版本,出现了一个新问题:Please check your network settings and try again.[2603]还是死活登录不上,简直离了大谱。

bf3f5509-b644-46f8-b3fc-c10eff316947.png

后来在微软社区里找了找,发现只需要在Internet选项里,勾上“TLS1.2”就行了。

tempsnip.png