« 爆速で沈みかけの船を操舵するの | トップページ | 「爆速経営―新生ヤフーの500日」蛯谷敏(著)日経BP社 »

2013.11.21

ファイル転送プロトコルYMODEM(ワイモデム)におけるCRC16の計算について

ファイル転送プロトコルYMODEM(ワイモデム)のCRCの計算範囲がわからなかったので、調べてみたのですが、明快な答えが得られず。結局Tera Termを使って現物合わせで確認したので、ここに書いておきます。

YMODEMの転送ブロックは、以下のように1029バイト、または133バイト。ここで、最後のCRCは、どこからどこまでのバイト列を計算すればよいのか?ということです。

  1. ヘッダー1バイト(STXかSOH)
  2. ブロック番号1バイト
  3. ブロック番号の1の補数(ビット反転)1バイト
  4. データ部(1がSTXなら1024、SOHなら128バイト)
  5. CRC2バイト(CRC-16)

あらゆる可能性を否定せず(笑)いろいろ試してみましたら、なんと!「データ部の後ろに0x00を2バイト追加して計算する」という、「そらわからんわー」ってな結果でした。

追加の2バイトは仮のCRCだとの噂。どこかの掲示板に、「CRCの部分を0としてブロック丸ごと計算するような、気がする・・・」という記述があって、丸ごとじゃなかったけれど、どうにか正解にたどり着けた感じです。

androidに実装するのが目的なので、CRCの計算ルーチンとして、適当なところからCRC16CCITTってクラス(MITライセンス)を拾ってきたのですが、これの結果がまた合わないというトラップにも引っかかった。最終的にXMODEM/YMODEM PROTOCOL REFERENCE(←コレ、本家本元の仕様書ですね)にK&Rのソースが掲載されていた(以下に引用)のを見つけて、ありがたくJavaに書き換えて大成功。

unsigned short
updcrc(c, crc)
register c;
register unsigned crc;
{
    register count;
    for (count=8; --count>=0;) {
        if (crc & 0x8000) {
            crc <<= 1;
            crc += (((c<<=1) & 0400) != 0);
            crc ^= 0x1021;
        }
        else {
            crc <<= 1;
            crc += (((c<<=1) & 0400) != 0);
        }
    }
    return crc;
}

この本家本元の仕様書には、CRCの計算範囲についてちゃんと書かれているのでしょうね。英語なのでまともに読んでいない(それがアカン)。でも、この仕様書を探すのにも結構苦労したんよね。

もいっちょトラップ。Tera Termへファイルを送信しているとき、最後のブロックを送った後直後のEOT送信はNAK応答です。もう一回EOTを送るとACKを返してきて完了。必ずそうなっているみたいです。受信時は初回のEOTにACK応答でも問題無かったようですが。ようわかりません。

CRC、EOTの件など、何か意味のある仕様なんだろうけど、軽く考えても意味がわからん。


最後に2バイト0を追加する件ですが意味がわかりましたので、以下追記です。

0を2バイト追加して計算することで、チェックが単純化できるのだそうです。受信側では、データ部の後ろに計算結果のCRCが2バイト付いていますけど、この2バイトも含めて計算すると、アラ不思議!CRCが正しい場合は結果がゼロになるんですよ。

CRCは、論理回路でも処理しやすいらしいのですが、2つの値を比較するより、「結果がゼロか否か」という検査のほうが楽なんですね。実際に試してみたら、確かにゼロになっていました。

いやあ、数学って本当に美しいですね。それではさいなら。

« 爆速で沈みかけの船を操舵するの | トップページ | 「爆速経営―新生ヤフーの500日」蛯谷敏(著)日経BP社 »

プログラミング」カテゴリの記事

仕事」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

« 爆速で沈みかけの船を操舵するの | トップページ | 「爆速経営―新生ヤフーの500日」蛯谷敏(著)日経BP社 »

2020年7月
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
フォト

Google AdSense

銀の弾丸

無料ブログはココログ

他のアカウント