组件重构

本文探讨了组件重构中的关键点,包括 DaemonConfig.ini 的配置、全局变量的使用、回调函数中的变量处理、调试技巧、文件操作异常及数据包格式。强调了全局变量的谨慎使用,推荐将变量作为成员变量,并提供了避免内存问题的解决方案。同时提醒注意调试时正确选择程序,以及在数据传输中重视安全性而非速度。
摘要由CSDN通过智能技术生成

知识点没有顺序:
按照A4纸整理
1、 关于DaemonConfig.ini
可以设置多播的数值,如果希望多台设备共同接收数据火或者发送数据,则将多播的IP地址和端口号设置相同

如果接收到的主题混乱,在使用上面方式之后,仍然没有用,可以考虑改变字符编码格式。

2、 对于全局变量的使用
如果一个变量只是在本类中使用,将这个变量定义为成员变量;

对于static类型的回调函数,在这个函数里使用成员变量,有两种解决方法:
(1) 将成员变量定义为static,在类外初始化
(2) 定义本类指针,例如:static CompInfoRecv *g_CompInfoRecvPtr;
使用静态本类指针调用成员变量,例如:g_CompInfoRecvPtr->m_Index,这样在回调函数中可以使用成员变量,同时不需要将成员变量设置为static.

使用全局变量的时候,会结合extern关键字,这个有什么作用呢?
答:C++允许将定义和声明分离开来。
变量的声明规定了变量的类型和名字,即使一个名字被程序所知。一个文件如果想使用别处定义的名字则必须包含对那个名字的声明。
定义则负责创建与名字关联的实体,定义还申请空间存储。

如果向声明一个变量而非定义它,就在变量名之前加extern关键字,而不要显式地初始化变量;
例如:
extern int i; //声明i,而非定义I
注意:一个文件中这样声明i,如果想要i正常使用,必须在其他地方对i进行了初始化
如果i在一个文件中已经声明定义,则在另一个文件中,使用extern int i,则在这个文件中不需要重新定义I,并且可以正常使用i;

Int j; //声明并且定义j

但是我们也可以使用extern关键字给变量一个初始值,但这样就不是一个声明了,而是一个定义
Extern int v=2;
Int v=2;
//这两个语句完全一样,都是v的定义。

补充:
1、 将变量设置为全局变量,意将这个变量为所有类共享
2、 如果变量只是在本类中使用,将这个变量定义为成员变量
3、 对于static回调函数里面使用的变量不一定要是static,可以使用static类型的本类对象调用这些成员变量
4、 全局变谨慎使用
一般全局变量会被定义为指针类型,指针本身只占用4个字节,这样不会占用太多内存
5、 使用extern时,需要包含变量定义所在的头文件
extern只是声明这个变量,需要包含对应的头文件这样才可以找到变量定义的位置。

3、 全局变量、局部变量、类成员变量
错误的使用:
//全局变量
Char* filePath=”C:/ComponentRepository/”;
Void EvoSphere::CompInfoRecv::CreateCompontPack。et(const char compName)
{
//将组件名拼接到路径的后面
string tmpCompPath;
tmpCompPath.assign(EVO_COMPONENT_REPOSITORY_ROOT_DIR).append((char
)compName).append("/");
//自动创建文件夹
createNewFileDir((char*)tmpCompPath.data());//string 转 char*
filePath=(char*) tmpCompPath;
printf(“OnFuncCompRequestRecv fileNamePath totalPath=%s\n”, fileNamePath);
}
//注意:这样写肯定是错误的:
将局部变量tmpCompPath赋值给filePath,这时候这两个指针指向同一块内存,当这个函数运行结束后,这个局部变量的所指向的内存将会被释放,这时候指针filePath将变为野指针。同时也没有实现路径保存的效果。

解决方法:
在类中定义成员变量char数组
Char filePath[256];
Void EvoSphere::CompInfoRecv::CreateComponentPacket(const char compName)
{
//将组件名拼接到路径的后面
string tmpCompPath;
tmpCompPath.assign(EVO_COMPONENT_REPOSITORY_ROOT_DIR).append((char
)compName).append("/");
//自动创建文件夹
createNewFileDir((char*)tmpCompPath.data());//string 转 char*
strcpy(fileNamePath, tmpCompPath.c_str());
printf(“OnFuncCompRequestRecv fileNamePath totalPath=%s\n”, fileNamePath);
}
将路径保存到新开辟的内存空间中,这样局部变量释放后,路径仍然被保存下来。

4、 关于调试
出现的问题:当前不会命中断点,还没有为该文档加载任何符号
错误原因:进行调试的程序与你当前打断点的地方是不一致的

若想调试CompCtrlMonitorLib中的代码,其对应的exe程序是NodeAgent.exe
应该调试NodeAgent.exe程序。
我的错误是:调试了DeployMonitorTool.exe

5、 关闭文件异常fclose(fp)
关闭文件的时候会把内存缓冲区中的数据刷到文件里
可能关闭文件失败的原因:向文件中写了很多的数据(假设内存放的下),但是磁盘上没有空间了,这个时候,你一旦fclose(fp),这么多的数据就会刷到文件中,此时磁盘是装不了这么多的数据的。所以会关闭文件异常

if (s_configInfo.s_filePtr != NULL)
{
if (fwrite(iMessage, iLen, 1, s_configInfo.s_filePtr) != 1)
{
printf(“OnCompInfoRequest 写入文件失败!\n”);
return;
}
fflush(s_configInfo.s_filePtr); //将数据从内存缓冲区刷到文件中
}

关闭文件异常还有可能是:文件没有正常打开,文件句柄为NULL

6、 关于发送数据与接收数据包的格式
CompInfoSend.h CompInfoRecv.h
注:接收数据的回调函数使用了很多巧妙的方法,值得多看几遍。

组件id 序列号 有效长度 文件包

  1. 文件包里存放着每次发送的数据段Message
  2. 根据序列号,得知文件包里存放的数据类型
  3. 规范化结构体可能会浪费一点内存空间
  4. 对于通讯而言(文件传输):数据安全性优于数据传输速率
  5. 文件句柄打开或关闭的延时不要太长

发送端数据结构体:
//4+4+4+1024
struct MsgFileBlock
{
int s_Id; //文件标识
int s_SerialNum; //序列号
int s_Length; //文件包的有效长度
char s_BlockBuf[1024]; //文件包大小
char s_BlockTotalBuf[1036]; //整个文件包的大小

//结构体里可以构造无参、有参构造函数,也可以编写各种函数,像类一样使用
MsgFileBlock()
{
s_Id = 0;
s_SerialNum = 0;
s_Length = 0;
memset(s_BlockBuf, ‘0’, 1024);
memset(s_BlockTotalBuf, ‘0’, 1036);
}

}MsgBlock;

7、

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值