Wie kann ich mit C# die Ausrüstung des Instruments ändern? Da das Instrumentensteuerungsprogramm in C# entwickelt wurde, ist es am besten, wenn der Client C# ist. Um Datenverkehr zu sparen (der Server wird basierend auf dem Datenverkehr abgerechnet), müssen die Dateien komprimiert und die Dateikomprimierungsfunktion unter C# implementiert werden. Der Server wählt Java, um eine erholsame API zum Hochladen zu erstellen.
Gemäß den Anforderungen des Leiters muss ein Instrument geändert, einige Funktionen hinzugefügt und Messdaten auf den Server hochgeladen werden. Der Messzyklus des Instruments beträgt etwa 20 Sekunden, und die Datenmenge ist derzeit nicht groß. Jede Messung beträgt etwa weniger als 2 Millionen, und es handelt sich ausschließlich um Gleitkommadaten und Ganzzahldaten.
Zuerst wollte ich eine lange TCP-Verbindung verwenden, berücksichtigte aber die Umgebung vor Ort. In einer typischen Fertigungswerkstatt ist die elektromagnetische Umgebung komplex und das Netzwerksignal instabil, sodass die Implementierung einer langen TCP-Verbindung nicht in Betracht gezogen wird. Auch kurze Verbindungen werden in Zukunft nicht berücksichtigt, wenn die Anzahl der Geräte zunimmt. Auch die Kosten für den häufigen Verbindungsaufbau werden sehr hoch sein und der Server kann dies möglicherweise nicht ertragen (die Bettlerversion von Alibaba Cloud). Deshalb habe ich mich für die Verwendung von Restful für die Übermittlung entschieden, und die HTTP-Kommunikation kann mit Multithreads geplant werden.
Das Instrumentensteuerungsprogramm ist in C# entwickelt, sodass der Client am besten in C# läuft. Ich möchte Springboot auf der Serverseite verwenden, was sehr praktisch ist.
Da die neue Upload-Funktion den vorherigen Messtakt nicht beeinflussen kann, ist für ihre Implementierung Multithreading erforderlich. Leider bin ich faul und möchte Probleme mit der Thread-Koordination nicht berücksichtigen. Deshalb habe ich mich schließlich für die Implementierung der Nachrichtenwarteschlange entschieden.
Um Datenverkehr zu sparen (der Server wird je nach Datenverkehr abgerechnet), müssen die Dateien komprimiert werden und die Dateikomprimierungsfunktion muss in C# implementiert werden.
Daten aus der Messdatei lesen, die Parameter in der Datenbank speichern und die ursprünglichen Messdaten auf dem Dateiserver verpacken.
Die endgültige technische Lösung besteht darin, C# als Client und Java zum Erstellen der serverseitigen Restful-API zu verwenden Hochladen
Die Gesamtarchitektur ist wie folgt:
Die verwendete Technologie ist wie folgt:
C#'s Restful Client: RestSharp
Java Restful Server: Springboot
C#-seitige Nachrichtenwarteschlange: NetMQ
C#-Seiten-Zip-Operationskomponente:DotNetZip
Java-Seiten-Zip-Operationskomponente: Apache Commons Compress
Die Der Server verwendet Springboot Restful, POST-Methode, sehr einfach.
MultipartFile wird zum Übertragen von Dateien verwendet, da ResrSharp des Clients Dateien nur auf diese Weise übertragen kann
@RestController @RequestMapping(value = "upload") public class FileRestController { Logger logger = LogManager.getLogger(FileRestController.class); @RequestMapping(value = "file", method = RequestMethod.POST) public @ResponseBody RestResult getZipFile(@RequestParam("file") MultipartFile file) throws IOException, URISyntaxException { RestResult result = new RestResult(); if (!file.getName().isEmpty()) { InputStream stream = file.getInputStream(); // String directory = FileRestController.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath(); String directory = "/usr/local/haliang/files/"; try { directory = URLDecoder.decode(directory, "utf-8"); } catch (java.io.UnsupportedEncodingException e) { return null; } FileOutputStream fs = new FileOutputStream(directory + file.getOriginalFilename()); logger.info("文件所在的目录: " + directory + "/files/" + file.getOriginalFilename()); byte[] buffer = new byte[1024 * 1024]; int bytesum = 0; int byteread = 0; while ((byteread = stream.read(buffer)) != -1) { bytesum += byteread; fs.write(buffer, 0, byteread); fs.flush(); } fs.close(); stream.close(); logger.info("成功接收文件: " + directory + file.getOriginalFilename()); } return result; } }
Die Client-Architektur ist wie folgt:
NetMQ ist die C#-portierte Version von ZeroMQ.
NetMQ (ZeroMQ zu .Net), ZMQ gilt als die schnellste Middleware in der Geschichte.
Es kapselt die Socket-Kommunikation, sodass wir komplexe Netzwerkkommunikation durchführen können, ohne Socket-Funktionsaufrufe schreiben zu müssen.
Der Unterschied zwischen ihm und Socket ist: Ein gewöhnlicher Socket ist eine End-to-End-Beziehung (1:1-Beziehung), aber ZMQ kann eine N:M-Beziehung haben. Die Leute wissen mehr über BSD-Sockets als Punkt-zu-Punkt-Verbindung. Eine Punkt-zu-Punkt-Verbindung erfordert den expliziten Aufbau einer Verbindung, die Zerstörung der Verbindung, die Auswahl des Protokolls (TCP/UDP) und die Behandlung von Fehlern usw. ZMQ schirmt diese Details ab und vereinfacht so Ihre Netzwerkprogrammierung.
Es handelt sich um eine Warteschlangenbibliothek für die Nachrichtenverarbeitung, die sich flexibel über mehrere Threads, Kerne und Host-Boxen hinweg skalieren lässt. Im Gegensatz zu den allgemeinen Nachrichtenwarteschlangenprodukten verfügt es nicht über einen Nachrichtenwarteschlangenserver, sondern ähnelt eher einer Netzwerkkommunikationsbibliothek. Aus Sicht der Netzwerkkommunikation liegt es oberhalb der Sitzungsschicht und unterhalb der Anwendungsschicht und gehört zur Transportschicht.
zeromq unterteilt die Nachrichtenkommunikation in vier Modelle, nämlich Eins-zu-Eins-Paar-Modell (Exclusive-Pair), Anfrage-Antwort-Modell (Request-Reply) und Publish -Subscribe-Modell (Publish-Subscribe), Push-Pull-Modell (Push-Pull). Diese vier Modelle fassen das allgemeine Netzwerkkommunikationsmodell zusammen. In der Praxis können Sie zwei oder mehr dieser Modelle kombinieren, um je nach Anwendungsanforderungen Ihre eigene Lösung zu bilden.
Das einfachste 1:1-Nachrichtenkommunikationsmodell, das zur Unterstützung des traditionellen TCP-Socket-Modells verwendet wird und hauptsächlich für prozessinterne Inter-Prozesse verwendet wird -Thread-Kommunikation. Es kann als TCP-Verbindung betrachtet werden, aber der TCP-Server kann nur eine Verbindung akzeptieren. Die Implementierung erfolgt sperrenfrei und ist sehr schnell. Daten können in beide Richtungen fließen, was sich vom späteren Anfrage-Antwort-Modell unterscheidet. (Nicht empfohlen, keine Beispiele)
由请求端发起请求,然后等待回应端应答。一个请求必须对应一个回应,从请求端的角度来看是发-收配对,从回应端的角度是收-发对。跟一对一结对模型的区别在于请求端可以是1~N个。
请求端和回应端都可以是1:N的模型。通常把1认为是server,N认为是Client。ZeroMQ可以很好的支持路由功能(实现路由功能的组件叫作Device),把1:N扩展为N:M(只需要加入若干路由节点)。从这个模型看,更底层的端点地址是对上层隐藏的。每个请求都隐含有回应地址,而应用则不关心它。通常把该模型主要用于远程调用及任务分配等。
(NetMQ请求响应C#调用案例)
发布端单向分发数据,且不关心是否把全部信息发送给订阅端。如果发布端开始发布信息时,订阅端尚未连接上来,则这些信息会被直接丢弃。订阅端未连接导致信息丢失的问题,可以通过与请求回应模型组合来解决。订阅端只负责接收,而不能反馈,且在订阅端消费速度慢于发布端的情况下,会在订阅端堆积数据。该模型主要用于数据分发。天气预报、微博明星粉丝可以应用这种经典模型。 (NetMQ发布订阅模式C#调用案例)
Server端作为Push端,而Client端作为Pull端,如果有多个Client端同时连接到Server端,则Server端会在内部做一个负载均衡,采用平均分配的算法,将所有消息均衡发布到Client端上。与发布订阅模型相比,推拉模型在没有消费者的情况下,发布的消息不会被消耗掉;在消费者能力不够的情况下,能够提供多消费者并行消费解决方案。该模型主要用于多任务并行。
(NetMQ推拉模式C#调用案例)
TCP:ZeroMQ基于消息,消息模式,而非字节流。
XMPP:ZeroMQ更简单、快速、更底层。Jabber可建在ZeroMQ之上。
AMQP:完成相同的工作,ZeroMQ要快100倍,而且不需要代理(规范更简洁——少278页)
IPC:ZeroMQ可以跨多个主机盒,而非单台机器。
CORBA:ZeroMQ不会将复杂到恐怖的消息格式强加于你。
RPC:ZeroMQ完全是异步的,你可以随时增加/删除参与者。
RFC 1149:ZeroMQ比它快多了!
29west LBM:ZeroMQ是自由软件!
IBM低延迟:ZeroMQ是自由软件!
Tibco:仍然是自由软件!
一般都是发布者先启动,绑定监听端口。封装了一个发送函数,主要是发送原先软件生成测量文件的路径。
public class Publisher { public int Port { get; set; } private PublisherSocket socket; /// <summary> /// 构造函数 /// </summary> /// <param name="port">绑定的端口</param> public Publisher(int port) { Port = port; } /// <summary> /// 启动发布端 /// </summary> public void Start() { NetMQContext context = NetMQContext.Create(); this.socket = context.CreatePublisherSocket(); this.socket.Bind("tcp://127.0.0.1:" + Port); } /// <summary> /// 发送数据 /// </summary> /// <param name="result"></param> public void Send(string result) { socket.SendFrame(result); } }
订阅者启动时候连接端口。防止线程阻塞,订阅者是新开一个线程运行的。
public class Subscribe { private delegate void GetDataHandler(string message); private event GetDataHandler onGetData; public int Port { get; set; } public string TempDirectory { get; set; } public bool isRunning { get; set; } public string domain { get; set; } public Subscribe(int port, string domain) { Port = port; this.domain = domain; onGetData += ProcessData; } private SubscriberSocket socket; public void Start() { this.isRunning = true; NetMQContext context = NetMQContext.Create(); socket = context.CreateSubscriberSocket(); socket.Connect("tcp://127.0.0.1:" + Port); socket.Subscribe(""); Thread t = new Thread(new ThreadStart(StartSub)); t.Start(); } private void StartSub() { while (isRunning) { Thread.Sleep(10000); string result = socket.ReceiveFrameString(Encoding.UTF8); onGetData(result); } } private void ProcessData(string path) { Console.WriteLine("收到文件:" + path); string compressedFile = Compress.CompressFile(TempDirectory, path); new RestPost(domain).Post(compressedFile); }
压缩使用DotNetZip组件,非常简单好用。
public class Compress { public static string CompressFile(string temp,string txtPath) { string txtFileName = System.IO.Path.GetFileNameWithoutExtension(txtPath); string compressedFileName = temp+"/"+txtFileName + ".zip"; ZipFile file=new ZipFile(); file.AddFile(txtPath,""); file.Save(compressedFileName); return compressedFileName; } }
使用RestSharp组件,也是非常简单。异步回调,不影响性能。
public class RestPost { public string Domain { get; set; } public RestPost(string domain) { Domain = domain; } public void Post(string path) { RestRequest request = new RestRequest(Method.POST); request.AddFile("file", path); RestClient client = new RestClient {BaseUrl = new Uri("http://" + Domain + "/upload/file")}; client.ExecuteAsync(request, (response) => { if (response.StatusCode == HttpStatusCode.OK) { Console.WriteLine("上传成功...\n" + response.Content); } else { Console.WriteLine($"出错啦:{response.Content}"); } } ); } }
写代码之前一定要搞清楚需求,设计好架构
注意消息队列启动时候的线程问题
异步执行
相关文章:
相关视频:
Das obige ist der detaillierte Inhalt vonTechnologie zur Modifikation von Instrumenten und Geräten, um die Funktion des Hochladens von Messdaten auf den Server zu realisieren. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!