C# Thrift 实战开发 从PLC到Thrift再到客户端集成开发
2021-04-25 06:25
标签:运行 value 名称 UI while nes ruby 说明 cal 本文并不是说明Thrift设计及原理的,直接拿Thrift来开发一个Demo程序,如果想要了解Thrift的细节,可以访问官方网站:https://thrift.apache.org/ 官方的网站上除了介绍说明外,当然还有白皮书,详细的说明Thrift是干嘛用的。 简单的说,Thrift可以作为一个中间数据站,我们可以将数据丢到Thrift上,等待客户端的请求,而这个客户端可能是C#程序,当然也有可能是java程序,甚至是php,ruby,python等等,就像白皮书的介绍一样,一个灵活的,可伸缩的,多语言的服务集成。 关于本项目的意图,基于对Thrift简单的学习后,就想要拿个Demo进行练手,模拟一些实际的操作,顺便测试测试一些东西,加强自己对Thrift的理解,才能判别这个技术是否真的适合你。 大致介绍下本项目,本项目主体功能是,服务器端程序不停的读取西门子PLC进行数据更新,并将数据刷新到Thrift,客户端调用Thrift服务来访问服务器的数据,除此之外,实现一个操作,在客户端做一个按钮,点击按钮后,将一个数据(通过服务器程序中转)写入到PLC中,并返回是否写入成功的标记。 其他的功能就是测试测试连接稳定性,网络重连机制的试验。 说了那么多,赶紧开始吧,此处我的IDE时VS2017,先创建一个简单的winform项目吧。在这个解决方案里,共创建2个窗体程序,一个服务端,一个客户端,再创建一个库项目,用来生成客户端和服务器共用的代码服务。就像下面这样子 接下来我们既然要读取PLC的数据,使用Thrift技术。那么我们就要进行安装相关的插件支持,我们在NuGet界面上进行安装两个插件,Thrift和HslCommunication,对于Thrift而言,三个项目都需要安装,对于HslCommunication只需要安装到服务器: 安装HslCommunication OK,到这里为止,我们前期的准备工作基本完成,接下来需要设计读取的数据和实现的功能,以这个为前提去设计Thrift的实现接口。 有了上述的基础设计后,接下来就是设计Thrift这一层希望提供什么样子的接口操作了,此处我们就举一些简单的例子,首先呢,设备不会只有一台,我们就假设有好多台设备,每台设备有如下参数信息: 然后在Thrift中,我们希望公开的数据有获取单台设备的信息,也有针对报警中的统计信息。获取所有设备运行状态的json数据,所有设备报警状态的json数据,单独获取所有设备的温度数据,单独获取所有设备的压力值,最后再提供一个允许手动更改设备状态的接口,参考了官方的白皮书(地址为:https://thrift.apache.org/static/files/thrift-20070401.pdf),最终完成的Demo.thrift文件如下: 这个文件存放的目录在下面这个目录,和安装thrift的package目录一致: 接下来就是调用上图中的thrift-0.9.1.exe来生成代码了,具体方式如下: 打开电脑的cmd指令(也就是命令提示符): 然后cd到上面的目录里去,指令为cd /d 目录,结果如下: 输入thrift-0.9.1.exe -help ok,到这里为止,我们知道了怎么去生成C# 代码了:指令如下:thrift-0.9.1.exe --gen csharp Demo.thrift 然后我们就看到路径下多了一个文件夹 点进去后就是: 就是我们之前填写的信息生成的文件。接下来,把这两个文件添加到一开始我们创建的三个项目的Common项目中去: 重新生成Common项目,OK,到这里为止,我们前期的任务都完成了,接下来就是真正写代码的时候了。 在Server端要做的第一件事就是添加对Common项目生成的dll组件的引用,第二件事是创建一个类,继承Common项目中的一个接口:如下: 接下来就实现这些具体代码了。 主要功能就是实例化了一个数组,拥有十个设备,我们只有一台PLC,就模拟读取一个就行了,但数组的操作需要加同步锁,这里我们还要添加一个写入数据的功能,这个功能应该在外面实现。至此,我们可以开发真正的服务器代码了: server上项目的form1窗口上添加两个按钮,分别为启动,和停止,都触发一个事件,然后在代码里完成Thrift的初始化: 接下来需要完成读取PLC数据,并提供一个方法WritePlc实现数据的真正写入,此处由于我只有一个PLC所以,就方便实现了读写,不再区分多个设备。 到这里为止,我们已经把服务器端的程序都已经开发完成了,已经可以生成并运行了。 服务器端开发完成后,客户端就相对容易多了,实例化变量名,并初始化后,就可以随便使用了: 增加几个按钮及显示框之后,增加一个定时读取服务器各机台状态并实时更新界面的功能: 所有的代码都已经写完,接下来就是最终演示了: 但是在三条线程的压力测试中,会出现异常,内部同步机制可能没有做好,不知道什么原因,如果你知道,本人非常感谢! 技术支持QQ群:592132877 本项目的github地址:https://github.com/dathlin/ThriftDemo C# Thrift 实战开发 从PLC到Thrift再到客户端集成开发 标签:运行 value 名称 UI while nes ruby 说明 cal 原文地址:http://www.cnblogs.com/dathlin/p/7911972.htmlAbout Thrift:
About Demo:
Getting Started
程序架构设计如下:
Server Implementation
namespace Thrift.Server
{
public class PublicServiceHandle : ThriftInterface.PublicService.Iface
{
public int GetAlarmCount()
{
throw new NotImplementedException();
}
public List
namespace Thrift.Server
{
public class PublicServiceHandle : ThriftInterface.PublicService.Iface
{
#region Constructor
///
private PublicServiceHandle handler;
private TServer server;
private void userButton1_Click(object sender, EventArgs e)
{
new System.Threading.Thread(() =>
{
// 启动服务
handler = new PublicServiceHandle(WritePlc);
var processor = new ThriftInterface.PublicService.Processor(handler);
TServerTransport transport = new TServerSocket(9090);
server = new TThreadPoolServer(processor, transport);
server.Serve();
})
{
IsBackground = true
}.Start();
// 启动定时器去读取PLC数据
timerReadPLC.Start();
}
private void userButton2_Click(object sender, EventArgs e)
{
// 关闭服务
server?.Stop();
}
#region PLC Connection
private SiemensTcpNet siemensTcp; // 和PLC的核心连接引擎
private Timer timerReadPLC; // 读取PLC的定时器
#endregion
private void Form1_Load(object sender, EventArgs e)
{
siemensTcp = new SiemensTcpNet(SiemensPLCS.S1200)
{
PLCIpAddress = System.Net.IPAddress.Parse("192.168.1.195")
};
// 连接到PLC
siemensTcp.ConnectServer();
timerReadPLC = new Timer();
timerReadPLC.Interval = 1000;
timerReadPLC.Tick += TimerReadPLC_Tick;
}
private void TimerReadPLC_Tick(object sender, EventArgs e)
{
// 每秒执行一次去读取PLC数据,此处简便操作,放在前台执行,正常逻辑应该放到后台
HslCommunication.OperateResult
Client Implementation
private ThriftInterface.PublicService.Client client;
private void Form1_Load(object sender, EventArgs e)
{
var transport = new TSocket("localhost", 9090);
var protocol = new TBinaryProtocol(transport);
client = new ThriftInterface.PublicService.Client(protocol);
transport.Open();
// 启动后台线程实时更新机器状态
thread = new System.Threading.Thread(ThreadRead);
thread.IsBackground = false;
thread.Start();
}
System.Threading.Thread thread;
private void ThreadRead()
{
while(true)
{
System.Threading.Thread.Sleep(1000);
JArray jArray = JArray.Parse(client.GetJsonMachineState());
int[] values = new int[10];
// 解析开始
for (int i = 0; i ();
}
if(IsHandleCreated) Invoke(new Action(() =>
{
label1.Text = values[0].ToString();
label2.Text = values[1].ToString();
label3.Text = values[2].ToString();
label4.Text = values[3].ToString();
label5.Text = values[4].ToString();
label6.Text = values[5].ToString();
label7.Text = values[6].ToString();
label8.Text = values[7].ToString();
label9.Text = values[8].ToString();
label10.Text = values[9].ToString();
}));
}
}
private void ShowMessage(string msg)
{
if(textBox1.InvokeRequired)
{
textBox1.Invoke(new Action
文章标题:C# Thrift 实战开发 从PLC到Thrift再到客户端集成开发
文章链接:http://soscw.com/essay/79281.html