UDP > ASCIIコード以外のunsigned char型変数値の送受信 > 0xE2が化ける問題

```txt:動作環境
C++ Builder XE4
```

## 前置き

UDP通信にて`<STX>`,`<ETX>`,`<BCC>`を含めたコードの送受信を試行している。
フォーマットとしては`<STX>ペイロード<ETX><BCC>`。
http://qiita.com/7of9/items/a91a396f03fac9516814

その際に、`<BCC>`として計算した値が`0xE2`などの場合に別のコードに変わってしまうという症状に遭遇している。

関連しそうなのは以下。
http://qiita.com/7of9/items/7bab0cf9f4311f1ebbd1

ASCIIコード
http://www9.plala.or.jp/sgwr-t/c_sub/ascii.html
0x00から0x7Fまで定義されている。

IndyのTidUDPServerなどでコードページ932で受信した時（もしくはchar型変換時)に0x80以降のコードが化けているという状況。

## ツールの動作確認

調査の前に、確実に動作するツールを確保しておく。

NonSoftさんのUDP/IPテストツールを使わせていただきます。
http://nonsoft.la.coocan.jp/Download/UdpTool/index.html

`AAA<E2>`というコードを2つのOS上で送受信してみた。
(以下、`0xE2`を`<E2>`と記載)
送信側も受信側もUDP/IPテストツールを使用した。

受信側で以下となり、`<E2>`のコードを含めて送受信は成功している。

```
接続                (6000 )
->受 192.168.0.31 (4000 )<41><41><41><e2>
```

以降の動作確認にUDP/IPテストツールを使うことで、不具合の絞込みが可能である。

### コードページ932での受信 > 文字化け

```Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
	IdUDPServer1->DefaultPort = 6000;
	IdUDPServer1->Active = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdUDPServer1UDPRead(TIdUDPListenerThread *AThread, const TIdBytes AData,
          TIdSocketHandle *ABinding)
{
	AnsiString rcvdStr;
	Idglobal::_di_IIdTextEncoding encSJIS;

	encSJIS = IndyTextEncoding(932);

	int init_pos = 0;
	rcvdStr = encSJIS->GetString(AData, init_pos, AData.Length);
	int nop=1; // for breakpoint
}
//---------------------------------------------------------------------------
```

上記のプログラムに対してUDP/IPテストツールから`AAA<E2>`を送信してみた。

受信文字列は`<41><41><41><81>`となった。
`<E2>`は`<81>`に化けてしまっている。

## 対応案

`<BCC>`の値にはunsigned char型の場合`<00>`から`<FF>`の任意の値が入る。`<80>`以降のコードも受信できるようにするためには、いくつかの対応案が考えられる。

### 1. すべてをBCDに変換する

`<80>`の場合、`8(<38>)`と`0(<30>)`に変換するというBCD(Binary Coded Decimal)表現を使う。
http://qiita.com/7of9/items/c9febc6d0403d8fd6c0e

これにより、送受信される文字列はつねにASCIIコードの値に収まる。
一方で、1バイトの文字を送受信するために2バイトが必要になるため、送受信データサイズが2倍になるという欠点はある。

こちらの方法は使用例をいくつか見たことがある。

### 2. `<BCC>`だけをBCDにする

`<STX>ペイロード<ETX><BCC>`という通信プロトコルの場合、文字化けが発生するのは`<BCC>`の部分だけ。(`<STX>`と`<ETX>`はASCIIコードのため文字化けしない。)

`<BCC>`の部分だけをBCDで変換するという案。

送受信データのサイズが抑えられる。

ただし、こちらの方法は標準的な方法ではないかもしれない。
(他の人の使用例を見た記憶がない）。

### 3. ペイロード,BCC値`<CR><LF>`にする

`<STX>ペイロード<ETX><BCC>`のように`<STX>`と`<ETX>`を使うことにこだわらない場合、以下のような形式にするということも考えられる。

```
ペイロード,<BCC(の数値)><CR><LF>
```

`<BCC>`が`<E2>`の場合、`<E2>`はunsigned char型では226になる。以下のようにして送受信するという案。

```
ペイロード,226<CR><LF>
```

利点としては、受信側はカンマ区切りでペイロードと`<BCC>`を分離できる。

欠点としては、`<STX>`と`<ETX>`がないため、送受信文字列の区切りが捉えにくくなる。UDP送受信でこれが問題になるかは未消化。

`<CF><LF>`終端でカンマ区切り文字列を送受信する例はRS-232C通信などでは多く見てきた。

UDPでは以下の記事内のリンク先に例がある。
http://qiita.com/7of9/items/1c44f6df88733ee586c1

(追記 2017/03/21)
シリアル通信では以下の「Packet type: 220」に`1F`のようなchecksumがある。
http://www.pvelectronics.co.uk/PA6B/PA6B_commands.pdf

### 4. コードページ932以外での送受信にする

ASCIIで受信する限りは文字化けが発生する。
ASCII(コードページ932)以外で受信するという案。

こちらについては調査不足。

1つの`<BCC>`の文字化け対策のために、関連するコードをすべて変更するのが良い案かは思案中。

### 他の案

他にも方法があるかもしれない。
それらの方法の選択の視点は「標準的な方法かどうか」。

### 5. `ToHex()`を使う案

@rryu さんのコメントをもとに見つけました。

http://qiita.com/7of9/items/72c018fe51b950a7d573