书合文秘网 - 设为首页 - 加入收藏
当前位置 首页 > 范文大全 > 公文范文 >

发射机房运行监控系统关键技术的解决方案

作者: 浏览数: 关键词: 监控系统 关键技术 机房 发射 解决方案


打开文本图片集

摘要:文章介绍了建设发射机房运行监控系统的关键技术难题,及其解决思路和方法。解决了发射台机房运行监控系统在和其他系统交换数据过程中,因使用不同的编程语言,而产生不同的汉字编码带来的相互转换难题;并实现了系统接收数据包以后,把字符串按需求拆分还原出相应的数据;还攻克了因网络中断、或者服务器关闭等原因,而产生的Socket连接超时难题。

关键词:系统开发;编码转换;字符拆分;连接超时

中图分类号:TP391 文献标识码:A 文章编号:1009-3044(2016)21-0204-03

无线电台管理局近年在大力推进信息化建设,整合现有的发射机单机自动化系统、天线自动交换系统、以及机房辅助系统,优化发射台安全播出设备的自动化系统,提高安全播出效果。机房运行监控系统结构如图1所示:

机房运行监控系统的作用就是统一调度管理全机房的播出任务,接收、解析由上一级平台下发的调度令,调整运行图,协调发射和天线自动化系统进行播出;集中管理全机房设备,统一监控,根据发射机房设备的运行状态和运行信息,进行代播申请和系统运行方式设置,并将运行状态信息和故障信息,进行记录、汇总和管理 。下面就开发过程中遇到的关键技术难题,做一个初步探讨和解析。

1 编码转换

机房运行监控系统和发射机单机自动化系统、天线交换系统、机房辅助系统、上一级台平台进行数据交换,如果是不同编程语言开发的系统,就存在一个汉字编码转换问题。例如微软的C++默认的汉字编码方式是GB2312,而Sun公司的Java默认的汉字编码方式是UTF-8,在进行通信时如果数据包里包含汉字,而没有进行编码转换,对方接收到的数据就变成不可知的乱码,不能正确解析。如何在GB2312与UTF-8之间相互转换?很多资料上讲解的编码转换通常是用字符串的转换,来进行2进制的运算,这就涉及大量的I/O操作,效率比较低,使用起来也很不方便。发射机自动化系统发送的数据包实时性要求很高,且编码转换的工作量往往非常大,因此不得不考虑效率的问题。在GB2312和UTF-8互换的时候,首先需要先转换成UNICOD,然后再转换成GB2312或UTF-8。根据UTF-8一个汉字要用3个字节,而UNICODE只用2个字节;找出对应关系,进行位操作,即可达到目的。实现UTF-8和UNICODE之间的转换,就可用二进制运算,代替字符串的转换,从而使问题简单化。经过查找大量相关资料,反复测试,笔者用VC++编写了一个GB2312和UTF-8相互转换函数。下面是UTF-8到GB2312具体的实现代码,反过来也可以实现GB2312到UTF-8的转换。

void CChineseCodeLib::UTF_8ToUnicode(WCHAR*pOut,char *pText) // UTF-8转换成Unicode

{ char* uchar = (char *)pOut;

uchar[1] = ((pText[0] & 0x0F) << 4) + ((pText[1] >> 2) & 0x0F);

uchar[0] = ((pText[1] & 0x03) << 6) + (pText[2] & 0x3F);

return; }

void CChineseCodeLib::UnicodeToGB2312(char* pOut,unsigned short uData) // Unicode 转换成GB2312

{WideCharToMultiByte(CP_ACP,NULL,&uData,1,pOut,sizeof(WCHAR),NULL,NULL);

return;}

void CChineseCodeLib::UTF_8ToGB2312(string &pOut, char *pText, int pLen) // UTF-8 转换成GB2312

{char * newBuf = new char[pLen];

char Ctemp[4];

memset(Ctemp,0,4);

int i =0; int j = 0;

while(i < pLen)

{if(pText[i] > 0)

{newBuf[j++] = pText[i++]; }

else

{WCHAR Wtemp;

UTF_8ToUnicode(&Wtemp,pText + i);

UnicodeToGB2312(Ctemp,Wtemp);

newBuf[j] = Ctemp[0];

newBuf[j + 1] = Ctemp[1];

i += 3; j += 2; }}

newBuf[j] = ""\0"";

pOut = newBuf;

delete []newBuf;

return; }

在和不同系统交换数据的过程中,涉及汉字编码转换的地方,直接调用上面的函数,即可轻松实现不同编码方式的转换。

2 字符串的自由拆分

根据无线局制定的《无线电台管理局信息化建设规范》,机房运行监控系统在和上一级台平台、发射机单机自动化系统、天线交换系统、机房辅助设备交换数据时,用Socket进行通信,传送的数据包中不同的数据量之间用“|”分隔,那么在接收端解包的时候也是用“|”,判断还原各个数据量。为了方便在程序中重复调用,将数据帧拆分代码封装成一个类,以下为具体实现方式。

数据拆分封装类Header Files代码:

SplitStr.h

class ClassSplitter

{private:

CString sign_GetSplitterData; //数据拆分标识

BOOL sign_SequenceAsOne; //连续拆分标识

CString m_CF_Data; //需要拆分的数据

public:

void GetSingleData(CStringArrayData &arrayData); //从数据帧中获取需要的数据

CString GetTotalData(); //获取需要拆分的数据帧

void SetTotal_Data(CString str_Data); //设置需要拆分的数据帧

BOOL GetSequenceAsOne_Data()//获取拆分的数据帧内容

{return sign_SequenceAsOneData;};

void SetSequenceAsOne_Data(BOOL Sing_SequenceAsOneData) //设置拆分的数据帧内容

{sign_SequenceAsOne = Sign_SequenceAsOneData;};

CString singn_GetSplitData()//获取数据拆分标识

{return sign_GetSplitterData;};

void sign_SetSplitData(CString sign_SplitData) //设置数据拆分标识

{sign_GetSplitterData = sing_SplitData;};

ClassSplitter();

virtual ~ClassSplitter(); };

数据拆分封装类Source Files代码:

ClassSplitter::ClassSplitter()

{SetDataSign(""); sign_SetSequenceAstrData(TRUE);sign_SetSplitData(",");}

ClassSplitter::~ClassSplitter()

{ }

void ClassSplitter::SetData(CString strData) //设置需要拆分的数据帧

{m_CF_Data = strData; m_CF_Data.TrimLeft();m_CF_Data.TrimRight();}

CString ClassSplitter::GetTotalData()

{ return m_CF_Data;}

void ClassSplitter::GetSingleData(CStringArrayData &arrayData) //拆分数据帧函数

{ CString strData = GetTotalData(); CString strSplitSign = Singn_GetSplitData();

if (strData.Right(1) != strSplitFlag) strData +=strSplitSign;

CString strTemp; int posSign =-1;

while ((posSign=strData.Find(strSplitSign,0)) != -1)

{strTemData= strData.Left(posSign);

if (!GetSequenceAsSingle()) arrayData.Add(strTemData);

else

{if (!strTemData.IsEmpty() && strTemData!="") arrayData.Add(strTemData); }

strData = strData.Right(strData.GetLength() - posSign - 1); }}

至此,完成了文本字符串拆分类的编写,可以根据需要随意拆分文本字符串。下面我举个具体的例子,当需要在某一窗体中接收数据包时,首先要在该窗体中声明这个类,然后根据需要编写代码。实现代码如下:

#include

#include "SplitStr.h"

ClassSplitter Split;

Cstring m_sText = “upExceptionMessage|FFFF|200|800|250”;

Splitter.SetSplitSignData("|");

Splitter.SetSequenceAsSingle(TRUE);

Splitter.SetData(m_sText);

CStringArrayData arrayDataData;

Splitter.GetSingleData(arrayData);

程序运行,即可得到下面的结果:

arrayData[0] = “upExceptionMessage”;arrayData[1] = “FFFF”;arrayData[2] = “200”;arrayData[3] = “8000”;

当系统从缓冲区读取到字符串后,就可用这样的拆分方法,把所需要的数据取出来,很简单吧!本文使用的是“|”分割传输的数据, 读者可以按自己的实际需要,把“|”换成相应的分割符,来实现字符串的自由拆分。

3 Socket连接超时

根据《无线电台管理局信息化建设规范》设计的客户端/服务器模式,机房运行监控系统对单机自动化系统、天线交换系统、机房辅助系统是服务器,而对上一级台平台就是客户端了,他们间用套接字(Socket)进行通信。通过套接字进行数据交换时,需要考虑:

1)当网络链路发生异常,不能正常通信时,需要有超时连接退出功能,提示连接中断信息,并进行重新连接,直到连接通信正常,或者被用户中断通信过程。

2)在数据交换过程中,因网络异常,出现不能正确交换数据时,程序应能自动存储中断数据,网络恢复正常连接后,重传中断数据。

套接字模式有阻塞和非阻塞两种工作模式。当使用socket()函数和WSASocket()函数创建socket连接时,默认的socket连接都为阻塞模式。在输入、输出操作完成之前,该函数所在的线程会一直处于等待状态,后续的执行函数因阻塞而不能返回相应的值。例如调用返回函数return()时,应用程序先检查数据是否完备,若数据不完整,则该线程就会处于等待状态,一直阻塞等待。为避免这种情况,一般创建Socket连接时,设置成非阻塞模式,设定一定的等待时间,进行超时判断。一般非阻塞模式套接比较难控制,笔者参考《Windows网络编程技术》和微软发布的MSDN帮助系统,做了如下改进:

设置一个时钟,当操作时间超过设定值,就触发一个超时命令,终止当前操作。使用VC++自带的时钟设置计时器,通过WM_TIMER回传消息,涉及这个过程的主要函数有: SetTimer()、OnMessagePending()和CancelBlockingCall()。

4 结束语

上述几点是建设发射机房运行监控系统中常见的关键技术难题,及解决方案,该方案的所有代码都在VC++中调试通过,并且在实际应用中实现可靠、稳定运行。

参考文献:

[1] 胡鸣. Windows网络编程技术[M].科学出版社, 2008.

[2] 梁伟.Visual C++网络编程经典案例详解[M].清华大学出版社, 2010.

[3] 孙鑫,余安萍.VC++深入详解[M].电子工业出版社,2004.

[4] 习玄辉, 发射台机房运行监控系统的设计和应用[J].广播与电视技术,2013,40(1):91-93.

相关文章:

Top