よくある通信系プログラムのバグを示します。なお、細かい部分は通信規格によって変わりますので、場合によっては読み替えてください。
通信系プログラムでは、何らかの通信経路が必要です。物理的なものであれば、例えば、「ケーブルが接続してあるか」「ケーブルが断線していないか」「ピンが折れてないか」などが考えられます。
郵便ハガキに郵便番号と住所を記載するように、通信するには、お互いの情報が必要です。UDPなら、ポート番号、IPアドレスなどです。例えば、図2の場合を考えます。
図2は、クライアントとサーバのポート番号が異なっている例です。このように、設定値が正しくないと、データが送信できても、受信側プログラムには届きません。
通信系のプログラムでは、双方が意図したデータを送受信する必要があります。よって、どちらかが想定していないデータを送信すると意図しない結果となりますね。例えば、以下があります。
タイムアウトは、データが一定時間来なかった場合に実施する処理のことです。例えば、「データが5秒以上来なかった場合は、受信処理をやめる」などを指定できます。
タイムアウトを指定するのはいいのですが、タイムアウトの時間を「長くしすぎる」「短くしすぎる」ことが原因で、意図しない現象が発生します。
エンディアンとは、バイトの並び順のことです。世の中には、大きく分けて「リトルエンディアン」と「ビッグエンディアン」という並び順が存在します。
例えば、「short data = 0x1234;」というデータを定義することを考えます。リトルエンディアンだと、メモリ上には、「34」「12」の順番で並びます。一方、ビックエンディアンの場合は、「12」「34」となりますね。
筆者の経験上、通信関連ではビックエンディアンを使うことが多いでしょうが、たまにリトルエンディアンと混在し、バグとなることが少なくありません。その場合、受信バッファーからデータを取り出すと、データが逆転して現れるわけです。
「こんなバグが起こるわけがない」と思うかもしれませんが、筆者は数多く経験しています。原因は、「仕様を定義する段階でハードウェアが決まっていなかった」「仕様書にエンディアンの記載がない」「過去の経験上、ビッグエンディアンのはずだという思い込み」が原因でしょう。
一度に送信できるデータサイズには限りがあります。規定値を超えると、受信側には一括で届きません。その場合、「データが分割して届く」ことを考慮した「豪華なプログラム」にする必要があります。
ここからは、筆者がやってしまった通信系プログラムのバグを紹介します。
実機確認の場所が、会社の机から離れた場所にありました。よって、テストは試験場、プログラムの修正は自分の机で作業していました。あるとき、昨日まで動作していたはずのプログラムが正しく動作しないことが分かりました。「なぜ動作しないのだろう」と思ったのですが、原因は、作業場所によって設定を変更していたことが原因でした。
クライアント側のプログラムを作成していたときの話です。データを送信しても、相手側のエンジニアに「おかしなデータが来るのですが」といわれてしまいました。プログラムをよく見ると、構造体データが両者で異なっており、意図した変数にデータを格納できていませんでした。
こちらも、クライアント側のプログラムを作成していたときの話です。データを送信したところ、サーバ側の受信データの中身が逆転していました。「なぜデータが逆転しているのだろう」と悩んで他のエンジニアに相談しました。同僚エンジニアは、「多分、エンディアンが合ってないからだと思います」と即答しました。チェックすると、その通りでした。
Copyright © ITmedia, Inc. All Rights Reserved.