通过Indy加上俄语字母的SNMP陷阱

时间:2014-07-08 06:28:59

标签: c++builder snmp indy

我使用indy组件从borland c ++应用程序发送snmp陷阱,(感谢Remy Lebeau的工作示例Implementing SNMP SendTrap using Indy components)但是我对俄语字母有疑问。

void __fastcall TMainForm::QuickSendTrap()
{
String myEnterprise   = _D("1.5.5.5.5.5.5.5");
String eventType      = myEnterprise + _D(".1");
String eventDistance  = myEnterprise + _D(".2");
String eventTitle1     = myEnterprise + _D(".3");
String eventTitle2     = myEnterprise + _D(".4");
String eventTitle3     = myEnterprise + _D(".5");

TStringList *names = new TStringList;
names->Add(eventType);
names->Add(eventDistance);
names->Add(eventTitle1);
names->Add(eventTitle2);
names->Add(eventTitle3);

TStringList *values = new TStringList;
values->AddObject(_D("ftCritical"), (TObject*)ASN1_OCTSTR);
values->AddObject(_D("2.357"), (TObject*)ASN1_OCTSTR);
values->AddObject(_D("АБВГД"), (TObject*)ASN1_OCTSTR);
values->AddObject(_D("абвгд"), (TObject*)ASN1_OCTSTR);
values->AddObject(_D("ОПРСТ"), (TObject*)ASN1_OCTSTR);

TIdSNMP *idSnmp = new TIdSNMP(NULL);
idSnmp->QuickSendTrap(edHost->Text, myEnterprise, _D("public"), 162, 6, 1, names, values);
delete idSnmp;

delete names;
delete values;
}

而不是俄语符号Wireshark看到“?”

0000 30 81 8b 02 01 00 04 06 70 75 62 6c 69 63 a4 7e 0.......public.~ 0010 06 07 2d 05 05 05 05 05 05 40 04 c0 a8 64 56 02 ..-......@...dV. 0020 01 06 02 01 01 43 01 00 30 64 30 16 06 08 2d 05 .....C..0d0...-. 0030 05 05 05 05 05 01 04 0a 66 74 43 72 69 74 69 63 ........ftCritic 0040 61 6c 30 11 06 08 2d 05 05 05 05 05 05 02 04 05 al0...-......... 0050 32 2e 33 35 37 30 11 06 08 2d 05 05 05 05 05 05 2.3570...-...... 0060 03 04 05 3f 3f 3f 3f 3f 30 11 06 08 2d 05 05 05 ...?????0...-... 0070 05 05 05 04 04 05 3f 3f 3f 3f 3f 30 11 06 08 2d ......?????0...- 0080 05 05 05 05 05 05 05 04 05 3f 3f 3f 3f 3f .........?????

问题是如何正确编码俄罗斯字符串for snmp?

2 个答案:

答案 0 :(得分:1)

不幸的是,TIdSNMP目前不支持非ASCII数据。这是因为:

  1. Indy的ASN.1编码/解码函数尚未进行编码感知,因此可以使用字符集将字符串转换为字节数组。

  2. TSNMPInfo首先将PDU数据编码为String,然后在发送时使用Indy的8位编码将String编码为字节。因此,任何大于#255的Unicode代码点都将转换为?您尝试发送的俄语字符都具有大于#255的Unicode代码点值。没有选项可以指定不同的编码,即使ASN.1八位字节字符串在技术上可以携带任何编码的字符数据只要双方同意使用的字符集,就可以使用8位字符集。

答案 1 :(得分:0)

为了通过Indy的Snmp组件发送西里尔符号,我实现了隐藏"隐藏"在TIdSnmp使用的UnicodeString内的不同编码中的消息。

UnicodeString TMainForm::Windows1251ForSnmp(AnsiString str)
{
UnicodeString ustr = "";
for (int i = 0; i < str.Length(); i++)
{
  unsigned char cc = *(str.c_str()+i);
  wchar_t buff = 0;
  memcpy((char*)&buff, &cc, 1);
  ustr = ustr + buff;
}

return ustr;
}


UnicodeString TMainForm::Utf8ForSnmp(UTF8String str)
{
UnicodeString ustr = "";
for (int i = 0; i < str.Length(); i++)
{
  unsigned char cc = *(str.c_str()+i);
  wchar_t buff = 0;
  memcpy((char*)&buff, &cc, 1);
  ustr = ustr + buff;
}

return ustr;
}

UnicodeString TMainForm::Utf16ForSnmp(UnicodeString str)
{
UnicodeString ustr = "";
for (int i = 0; i < str.Length(); i++)
{
  unsigned int cc = *(str.c_str()+i);
  byte a = cc / 256;
  byte b = cc % 256;
  ustr = ustr + char(a);
  ustr = ustr + char(b);
}
return ustr;
}

通过其中一个函数进行消息转换后,我通常会将结果发送给Indy组件TIdSnmp,并且它会毫无问题地发送。

UnicodeString ustr = Windows1251ForSnmp("Русский");
UTF8String param = _D("Русский");
UnicodeString ustr2 = Utf8ForSnmp(param);
UnicodeString ustr3 = Utf16ForSnmp("Русский");

values->AddObject(ustr, (TObject*)ASN1_OCTSTR);
values->AddObject(ustr2, (TObject*)ASN1_OCTSTR);
values->AddObject(ustr3, (TObject*)ASN1_OCTSTR);

所以,在&#34;另一边&#34;我收到了Windows1251,Utf8和Utf16编码的俄语消息。