本文主要是介绍KY-RTI分布仿真技术:第八章 Visual C#程序设计,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
第八章 Visual C#程序设计
本章讲述如何基于Visual C#设计ping、pong程序。本质上是对上一章Visual C++程序的一次成功移植。对于不同的程序设计语言而言,基于HLA/RTI设计仿真应用的方法都差不多,而关键在于RTI软件能否支持相应程序设计语言的开发,用户关心一下调用接口即可,通过调用接口可以设计形式多样的程序。与C++调用接口的一个显著区别在于句柄和时间的表示,Visual C#中的各种句柄全部用int表示,各类时间则用double表示。Visual C#与Java编程风格相似,开发的仿真程序可以相互借鉴。
8.1需求分析
开发2个程序,一个为ping,一个为pong;两者都不使用tick服务。
这两个程序就像2个人打乒乓球一样,1个程序向另一个程序发送1个事件;另一个人收到事件后再给对方发送1个事件;如此循环往复。
8.2项目设计
按照需求,将要开发的两个程序叫做ping-notick和pong-notick。该项目与时间无关,不需要时间管理服务。本项目采用交互类,并借用KY-RTI的bin目录下已有的chat.fed文件来传输交互。该交互类名为chat,有name和sentence两个参数,如下列代码所示。
class chat { //交互类
string name; //参数
string sentence; //参数
}
在本项目中,两个程序的name分别设为“ping”和“pong”;sentence为要传输的字符串,其长度可变,具体的值由用户输入确定。
在本项目中存在一个问题,两个程序总有一个程序先启动,另一个后启动;先启动的程序需要等待另一个程序启动后再协同仿真。基于KY-RTI开发的仿真成员是面向多线程的,主线程负责向RTI发送请求;回调线程负责从RTI接收请求。本项目让ping-notick先启动,通过一个布尔变量来确定回调线程是否收到了回调消息,当收到了第1个回调消息时,表明pong-notick也已经启动了;pong-notick也通过一个布尔变量来确定回调线程是否收到了回调消息。
8.3 ping-notick代码设计
该程序由Program.cs和HwFederateAmbassador.cs两个文件组成。前者负责发送交互,后者负责从RTI接收交互,两者在执行时处于2个独立的线程中。在Program.cs中定义了2个类:Definitions和Program。Definitions类定义了一组静态变量,由主线程和回调线程共享,相当于C++语言中的全局变量,这与Java很像。
Program.cs代码说明:
12-24行:定义Definitions类;
14行:定义变量STEP,用来表示发送多少次交互后仿真结束,初始值为100;
15行:发送1个交互时要传输的字节数;
19-21行:定义交互类及其参数句柄变量;
35-41行:输入要传输的字节数;
43-49行:输入要发送的交互数;
58-64行:创建联邦执行;
66-81行:加入联邦执行;
88-92行:获取交互类及其参数句柄;
95行:公布交互类,只有公布之后才能够向RTI发送交互;
97行:订购交互类,只有订购之后才能够从RTI收到其他人的聊天内容;
99-102行:根据要发送的字节数生成字符串;
104-113行:生成要传输的交互信息,将name和sentence打包,后面直接调用sendInteraction发送;
123-132行:循环操作,每次等待回调线程收到交互,然后发送1个交互;
131-133行:如果发送的交互数不等于接收的交互数,则循环等待;
144-153行:退出联邦执行,不再参加仿真;
162-175行:销毁联邦。如果是最后一个仿真成员执行该操作,则整个仿真结束。
表8.1 Visual C# ping-notick示例:program.cs
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using RTI;
- using MID; //定义数据类型,例如HandleValuePair;
- using System.Threading; //for sleep
- using MYFED;
- namespace test
- {
- class Definitions
- {
- public static int STEP = 100;
- public static int data_size = 1024;
- public static int receivedInteractions = 0; //收到多少个交互
- //定义交互类句柄和参数句柄
- public static int hChatClass = -1; //对应chat.xml中的chat交互类
- public static int hChatName = -1; //对应chat交互类的name参数
- public static int hChatSentence = -1; //对应chat交互类的sentence参数
- public static bool received = false; //收到1个交互
- }
- class Program
- {
- static void Main(string[] args) {
- RTI.RTIambassador rti = null;
- string federationExecutionName = "chat"; //联盟名称
- string FEDfile = "chat.fed"; //FED文件
- string federateType = "ping"; //盟员名称
- Console.WriteLine("请输入要传输的字节数:"); //ping和pong要一致
- Definitions.data_size = int.Parse(Console.ReadLine());
- if (Definitions.data_size <= 0) {
- Console.WriteLine("字节数不正确");
- return;
- }
- Console.WriteLine("请输入交互次数:"); //ping和pong要一致
- Definitions.STEP = int.Parse(Console.ReadLine());
- if (Definitions.STEP < 1) {
- Console.WriteLine("交互次数不正确");
- return;
- }
- try {
- rti = new RTI.RTIambassador(); // libRTI provided
- MYFED.HwFederateAmbassador myfed = new MYFED.HwFederateAmbassador(); // User-defined
- RTI.FederateAmbassador fedAmb = (RTI.FederateAmbassador)myfed;
- int federateId;
- try {
- rti.createFederationExecution(federationExecutionName, FEDfile);
- } catch ( RTI.FederationExecutionAlreadyExists ) {
- Console.WriteLine("FED_HW: Note: Federation execution already exists.");
- } catch (Exception) {
- Console.WriteLine("FED_HW: ERROR: Failed to create federation execution.");
- }
- try {
- Console.WriteLine("FED_HW: JOINING FEDERATION EXECUTION: ");
- federateId = rti.joinFederationExecution( federateType,
- federationExecutionName,
- ref fedAmb);
- } catch (RTI.FederateAlreadyExecutionMember) {
- Console.WriteLine("FED_HW: ERROR: federate already exists in the Federation Execution " + federationExecutionName+".");
- return;
- } catch (RTI.FederationExecutionDoesNotExist) {
- Console.WriteLine("FED_HW: ERROR: Federation Execution does not exists.");
- return;
- } catch (Exception) {
- Console.WriteLine("FED_HW: ERROR: Failed to join federation execution.");
- return;
- }
- Console.WriteLine("FED_HW: JOINED SUCCESSFULLY: : Federate Handle = " + federateId);
- //
- //获取交互类句柄
- Definitions.hChatClass = rti.getInteractionClassHandle("chat");
- //获取交互类参数句柄
- Definitions.hChatName = rti.getParameterHandle("name", Definitions.hChatClass);
- Definitions.hChatSentence = rti.getParameterHandle("sentence", Definitions.hChatClass);
- //公布交互类,这样可以向RTI发送信息
- rti.publishInteractionClass(Definitions.hChatClass);
- //定购交互类,这样可以接受来自其它发布者的信息
- rti.subscribeInteractionClass(Definitions.hChatClass);
- string szSentence = "";
- for(int i=0; i<Definitions.data_size; i++) {
- szSentence+="a";
- }
- HandleValuePair[] pParams = new HandleValuePair[2];
- // Add Name
- pParams[0] = new HandleValuePair();
- pParams[0].aHandle = Definitions.hChatName;
- pParams[0].aValue = federateType;
- // Add Sentence
- pParams[1] = new HandleValuePair();
- pParams[1].aHandle = Definitions.hChatSentence;
- pParams[1].aValue = szSentence;
- for (int i = 0; i < Definitions.STEP; i++) {
- while (!Definitions.received) {
- Thread.Sleep(1); //睡眠1豪秒
- }
- Definitions.received = false; //不要放到rti.sendInteraction之后
- //发送交互,所有定购者(不包括自己)都会在HwFederateAmbassador.cpp中的receiveInteraction服务中收到该交互。
- try {
- rti.sendInteraction(Definitions.hChatClass, pParams, "");
- } catch(Exception) {
- Console.WriteLine("error for send interaction");
- }
- }
- while (Definitions.STEP != Definitions.receivedInteractions) { //如果发送的交互数不等于接收的交互数,则循环等待
- Thread.Sleep(1000); //睡眠1秒
- }
- //如果程序正常退出,则表明发送的交互数等于接收的交互数,没有丢失消息.
- } catch (RTI.ConcurrentAccessAttempted e) {
- Console.WriteLine(e.Message);
- return;
- } catch (Exception e) {
- Console.WriteLine("FED_HW: ERROR: this program meets an exception."+e.Message);
- return;
- }
- try {
- Console.WriteLine("FED_HW: RESIGN FEDERATION EXECUTION CALLED");
- rti.resignFederationExecution(
- ResignAction.DELETEOBJECTSANDRELEASEATTRIBUTES);
- Console.WriteLine("FED_HW: SUCCESSFUL RESIGN FEDERATION EXECUTION CALLED");
- } catch (Exception) {
- Console.WriteLine("FED_HW: ERROR: resign federation execution");
- return;
- }
- //------------------------------------------------------
- // Destroy the federation execution in case we are the
- // last federate. This will not do anything bad if there
- // other federates joined. The RTI will throw us an
- // exception telling us that other federates are joined
- // and we can just ignore that.
- //------------------------------------------------------
- try {
- Console.WriteLine("FED_HW: DESTROY FEDERATION EXECUTION CALLED");
- rti.destroyFederationExecution(federationExecutionName);
- Console.WriteLine("FED_HW: SUCCESSFUL DESTROY FEDERATION EXECUTION CALLED");
- } catch (RTI.FederatesCurrentlyJoined) {
- Console.WriteLine("FED_HW: FederatesCurrentlyJoined");
- return;
- } catch (RTI.FederationExecutionDoesNotExist) {
- Console.WriteLine("FED_HW: FederationExecutionDoesNotExist");
- return;
- } catch (Exception) {
- Console.WriteLine("FED_HW: ERROR: destroy federation execution");
- return;
- }
- }
- }
- }
|
HwFederateAmbassador.cs代码说明:
12-14行:由于不处理时间参数,因此如果接收到这种类型的receiveInteraction交互,则直接调用不带时间参数的服务来统一处理;
16-20行:通知主线程收到交互。
表8.2 Visual C#示例:HwFederateAmbassador.cs
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using MID; //定义数据类型,例如HandleValuePair
- using test;
- namespace MYFED
- {
- public class HwFederateAmbassador : RTI.FederateAmbassador
- {
- public override void receiveInteraction(int theInteraction, HandleValuePair[] theParameters, double theTime, string theTag, EventRetractionHandle theHandle) {
- receiveInteraction(theInteraction, theParameters, theTag);
- }
- public override void receiveInteraction(int theInteraction, HandleValuePair[] theParameters, string theTag) {
- Definitions.receivedInteractions++;
- Console.WriteLine(Definitions.receivedInteractions+" received an interaction from pong");
- Definitions.received = true;
- }
- }
- }
|
8.4 pong-notick代码设计
该程序由Program.cs和HwFederateAmbassador.cs两个文件组成。前者负责发送交互,后者负责从RTI接收交互,两者在执行时处于2个独立的线程中。在Program.cs中定义了2个类:Definitions和Program。Definitions类定义了一组静态变量,由主线程和回调线程共享,相当于C++语言中的全局变量,这与Java很像。
Program.cs代码说明:
12-24行:定义Definitions类;
14行:定义变量STEP,用来表示发送多少次交互后仿真结束,初始值为100;
15行:发送1个交互时要传输的字节数;
19-21行:定义交互类及其参数句柄变量;
35-41行:输入要传输的字节数;
43-49行:输入要发送的交互数;
58-64行:创建联邦执行;
66-81行:加入联邦执行;
86-90行:获取交互类及其参数句柄;
93行:公布交互类,只有公布之后才能够向RTI发送交互;
95行:订购交互类,只有订购之后才能够从RTI收到其他人的聊天内容;
97-100行:根据要发送的字节数生成字符串;
102-111行:生成要传输的交互信息,将name和sentence打包,后面直接调用sendInteraction发送;
113-127行:循环操作,每次发送1个交互,然后等待回调线程收到交互;
129-131行:如果发送的交互数不等于接收的交互数,则循环等待;
142-151行:退出联邦执行,不再参加仿真;
160-173行:销毁联邦。如果是最后一个仿真成员执行该操作,则整个仿真结束。
表8.3 Visual C# pong示例:Program.cs
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using RTI;
- using MID; //定义数据类型,例如HandleValuePair;
- using System.Threading; //for sleep
- using MYFED;
- namespace test
- {
- class Definitions
- {
- public static int STEP = 100;
- public static int data_size = 1024;
- public static int receivedInteractions = 0; //收到多少个交互
- //定义交互类句柄和参数句柄
- public static int hChatClass = -1; //对应chat.xml中的chat交互类
- public static int hChatName = -1; //对应chat交互类的name参数
- public static int hChatSentence = -1; //对应chat交互类的sentence参数
- public static bool received = false; //收到1个交互
- }
- class Program
- {
- static void Main(string[] args) {
- RTI.RTIambassador rti = null;
- string federationExecutionName = "chat"; //联盟名称
- string FEDfile = "chat.fed"; //FED文件
- string federateType = "pong"; //盟员名称
- Console.WriteLine("请输入要传输的字节数:"); //ping和pong要一致
- Definitions.data_size = int.Parse(Console.ReadLine());
- if (Definitions.data_size <= 0) {
- Console.WriteLine("字节数不正确");
- return;
- }
- Console.WriteLine("请输入交互次数:"); //ping和pong要一致
- Definitions.STEP = int.Parse(Console.ReadLine());
- if (Definitions.STEP < 1) {
- Console.WriteLine("交互次数不正确");
- return;
- }
- try {
- rti = new RTI.RTIambassador();
- MYFED.HwFederateAmbassador myfed = new MYFED.HwFederateAmbassador();
- RTI.FederateAmbassador fedAmb = (RTI.FederateAmbassador)myfed;
- int federateId;
- try {
- rti.createFederationExecution(federationExecutionName, FEDfile);
- } catch ( RTI.FederationExecutionAlreadyExists) {
- Console.WriteLine("FED_HW: Note: Federation execution already exists.");
- } catch (Exception) {
- Console.WriteLine("FED_HW: ERROR: Failed to create federation execution.");
- }
- try {
- Console.WriteLine("FED_HW: JOINING FEDERATION EXECUTION: ");
- federateId = rti.joinFederationExecution( federateType,
- federationExecutionName,
- ref fedAmb);
- } catch (RTI.FederateAlreadyExecutionMember) {
- Console.WriteLine("FED_HW: ERROR: federate already exists in the Federation Execution " + federationExecutionName+".");
- return;
- } catch (RTI.FederationExecutionDoesNotExist) {
- Console.WriteLine("FED_HW: ERROR: Federation Execution does not exists.");
- return;
- } catch (Exception) {
- Console.WriteLine("FED_HW: ERROR: Failed to join federation execution.");
- return;
- }
- /
- //获取交互类句柄
- Definitions.hChatClass = rti.getInteractionClassHandle("chat");
- //获取交互类参数句柄
- Definitions.hChatName = rti.getParameterHandle("name", Definitions.hChatClass);
- Definitions.hChatSentence = rti.getParameterHandle("sentence", Definitions.hChatClass);
- //公布交互类,这样可以向RTI发送信息
- rti.publishInteractionClass(Definitions.hChatClass);
- //定购交互类,这样可以接受来自其它发布者的信息
- rti.subscribeInteractionClass(Definitions.hChatClass);
- string szSentence = "";
- for(int i=0; i<Definitions.data_size; i++) {
- szSentence+="a";
- }
- HandleValuePair[] pParams = new HandleValuePair[2];
- // Add Name
- pParams[0] = new HandleValuePair();
- pParams[0].aHandle = Definitions.hChatName;
- pParams[0].aValue = federateType;
- // Add Sentence
- pParams[1] = new HandleValuePair();
- pParams[1].aHandle = Definitions.hChatSentence;
- pParams[1].aValue = szSentence;
- for (int i = 0; i < Definitions.STEP; i++) {
- Definitions.received = false; //不要放到rti.sendInteraction之后
- //发送交互,所有定购者(不包括自己)都会在HwFederateAmbassador.cpp中的receiveInteraction服务中收到该交互。
- try {
- rti.sendInteraction(Definitions.hChatClass, pParams, "");
- } catch(Exception) {
- Console.WriteLine("error for send interaction");
- }
- while (!Definitions.received) {
- Thread.Sleep(1); //睡眠1豪秒
- }
- }
- while (Definitions.STEP != Definitions.receivedInteractions) { //如果发送的交互数不等于接收的交互数,则循环等待
- Thread.Sleep(1000); //睡眠1秒
- }
- //如果程序正常退出,则表明发送的交互数等于接收的交互数,没有丢失消息.
- } catch (RTI.ConcurrentAccessAttempted e) {
- Console.WriteLine(e.Message);
- return;
- } catch (Exception e) {
- Console.WriteLine("FED_HW: ERROR: this program meets an exception."+e.Message);
- return;
- }
- try {
- Console.WriteLine("FED_HW: RESIGN FEDERATION EXECUTION CALLED");
- rti.resignFederationExecution(
- ResignAction.DELETEOBJECTSANDRELEASEATTRIBUTES);
- Console.WriteLine("FED_HW: SUCCESSFUL RESIGN FEDERATION EXECUTION CALLED");
- } catch (Exception) {
- Console.WriteLine("FED_HW: ERROR: resign federation execution");
- return;
- }
- //------------------------------------------------------
- // Destroy the federation execution in case we are the
- // last federate. This will not do anything bad if there
- // other federates joined. The RTI will throw us an
- // exception telling us that other federates are joined
- // and we can just ignore that.
- //------------------------------------------------------
- try {
- Console.WriteLine("FED_HW: DESTROY FEDERATION EXECUTION CALLED");
- rti.destroyFederationExecution(federationExecutionName);
- Console.WriteLine("FED_HW: SUCCESSFUL DESTROY FEDERATION EXECUTION CALLED");
- } catch (RTI.FederatesCurrentlyJoined /* e */ ) {
- Console.WriteLine("FED_HW: FederatesCurrentlyJoined");
- return;
- } catch (RTI.FederationExecutionDoesNotExist) {
- Console.WriteLine("FED_HW: FederationExecutionDoesNotExist");
- return;
- } catch (Exception) {
- Console.WriteLine("FED_HW: ERROR: destroy federation execution");
- return;
- }
- }
- }
- }
|
HwFederateAmbassador.cs代码说明:
12-14行:由于不处理时间参数,因此如果接收到这种类型的receiveInteraction交互,则直接调用不带时间参数的服务来统一处理;
16-20行:通知主线程收到交互。
表8.4 Visual C# pong示例:HwFederateAmbassador.cs
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using MID; //定义数据类型,例如HandleValuePair
- using test;
- namespace MYFED
- {
- public class HwFederateAmbassador : RTI.FederateAmbassador
- {
- public override void receiveInteraction(int theInteraction, HandleValuePair[] theParameters, double theTime, string theTag, EventRetractionHandle theHandle) {
- receiveInteraction(theInteraction, theParameters, theTag);
- }
- public override void receiveInteraction(int theInteraction, HandleValuePair[] theParameters, string theTag) {
- Definitions.receivedInteractions++;
- Console.WriteLine(Definitions.receivedInteractions + " received an interaction from ping");
- Definitions.received = true;
- }
- }
- }
|
8.5编译运行
下面以Visual C# 2010为例说明编译运行过程。
第1步:编译。以ping-notick程序为例说明,pong-notick程序的设置与此相同。
(1)选择左侧“ping-notick”根节点,按右键选择“属性”,打开属性对话框。
图8.1 选择项目属性
(2)设置项目属性。通常取缺省值,但也有用户可能有特殊要求。譬如,在Visual C# 2010下,KY-RTI为.Net Framework 3.5和.Net Framework 4两种目标框架提供支持。
图8.2 设置目标框架
(3)添加引用。选择左侧“引用”节点,按右键选择“添加引用”。通过“浏览”找到KY-RTI\lib目录下的.dll文件,选择自己需要的.dll文件。
图8.3 添加引用
图8.4 浏览引用库
第2步:编译,生成可执行程序。
第3步:启动KY-RTI。注意,KY-RTI的IP地址和端口号要与RTI.rid一致。
第4步:开启两个终端,分别运行ping-notick和pong-notick这2个仿真成员,开始仿真。如图8.5和图8.6所示。在这个例子中,每次传输的字节数为100个字节,一共来回10次。另外,基于Visual C#开发程序,则程序不需要调用tick服务,否则会有1个警告。
图8.5 ping-notick运行结果
图8.6 pong-notick运行结果
KY-RTI的Linux、Windows版本和源码请联系作者:walt_lbq@163.com
KY-RTI分布仿真技术:前 言
KY-RTI分布仿真技术:第一章 简介
KY-RTI分布仿真技术:第二章 系统安装
KY-RTI分布仿真技术:第三章 KY-OMT对象模型模板工具
KY-RTI分布仿真技术:第四章 C++程序设计
KY-RTI分布仿真技术:第五章 Qt程序设计
KY-RTI分布仿真技术:第六章 Java程序设计
KY-RTI分布仿真技术:第七章 Visual C++程序设计
KY-RTI分布仿真技术:第八章 Visual C#程序设计
KY-RTI分布仿真技术:第九章 综合演示
KY-RTI分布仿真技术:附录1 分组聊天(HLA数据分发管理的应用)
KY-RTI分布仿真技术:附录2 大联邦(构建1000个成员的HLA/RTI仿真系统)
KY-RTI分布仿真技术:附录3 国产化(操作系统+CPUs)
这篇关于KY-RTI分布仿真技术:第八章 Visual C#程序设计的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!