COMMXでバイナリ受信

解決


みずき  2010-04-12 21:57:48  No: 38267

D6パーソナルで最近このサイトでご指導していただきCOMMXをインストールに成功しバイナリ通信(受信)をやろうと思っています。以前はテキストデータでしたのでコンポーネントにあるHELPのサンプルコードを使って比較的簡単にデータを取ることができていましたがバイナリで戸惑ってしまい、またバイナリ受信のサンプルもなかったため質問させていただきました。

含まれているデータは2バイトのshortint、4バイトのLongInt、4バイトのFloat、文字列などで頭のタグからの相対位置が分かっています。

参考になりそうなサンプルなどありましたらご教示をお願いします。


ささ  2010-04-13 05:24:16  No: 38268

データをテキストベースで送信して、受信側で解釈したら?


Base64  2010-04-14 02:54:11  No: 38269

バイナリーデータをBase64に変換出来るライブラリーが確かあったので
それで変換すれば文字ベースで送れるようにできると思いますよ。
(ネットで、Delphi Base64 で検索すれば結構あります。)


みずき  2010-04-15 21:39:05  No: 38270

ささ様、Base64様、回答をいただきありがとうございます。
ここで質問させていただいたのはCOMMXによる受信で、現段階ではCommXのヘルプのサンプルにあるCommX1.ReceiveBlockを使ってターミネーターまでのCharデータ群を読めるようにしていますので、質問としてはこのCharを切り出して2バイトのshortint、4バイトのLongInt、4バイトのFloat、文字列などに変換する方法はないかというものです。各データの頭の位置は分かっていますので何か関数みたいなものがあるのではないかと思っていましたがご紹介いただいたBase64を見たところやはりこのような力仕事が必要なのですね?

現在得られているある長さのCharデータからはバイト毎にord関数でバイト値が取れますので b[1] + b[2]*256 + b[3]*power(256,2)・・・のように計算してみようかと思っていますがFloatはどうするか、などなど勉強してみます。


Streamとハサミ  2010-04-16 09:32:03  No: 38271

Shortint(2byte)、LongInt(4byte)、Double(4byte)、文字列(長さDATA付き)などの異なる型のデータがメモリ上に順に並んでいる場合に、そこから各データの値を取り出すには Streamを使うのが簡単で便利。

type
  TMemoryStream = class(Classes.TMemoryStream);

var
  a: Shortint;
  b: LongInt;
  c: Double;
  .....
begin
  ReadSize := CommX.ReceiveBlock(Buf, MaxSize);
  ms := TMemoryStream.Create;
  ms.SetPointer(Buf, ReadSize);
  // 以下、並び順にデータを取り出す
  ms.Read(a, Sizeof(Shortint));
  ms.Read(b, Sizeof(Longint));
  ms.Read(c, Sizeof(Double));
  .......
  ms.Free;
end;


jazzin  2010-04-17 01:35:11  No: 38272

位置がわかっているのなら、各オフセット毎にキャスト等すれば取得できます。

// buf: Pointerに受け取ったデータが入っていて、
// +0にWord、+2にLongword、+6にDouble、+14に文字長(Word)、
// +16以降にchar配列、という並びの場合
var
  v1: Word;
  v2: Longword;
  v3: Double;
  len: Word;
  v4: string;
begin
  v1 := PWord(Integer(buf)+0)^;
  v2 := PLongword(Integer(buf)+2)^;
  v3 := PDouble(Integer(buf)+6)^;
  len := PWord(Integer(buf)+14)^;
  SetLength(v4, len);
  Move(Pointer(Integer(buf)+16)^, Pointer(v4)^, len);
end;

また、bufをPByteArrayな変数に代入するか、
もしくはbuf自身がPByteArrayであれば、

  v1 := PWord(@buf[0])^;
  v2 := PLongword(@buf[2])^;

このようにも書けます。


みずき  2010-04-20 04:45:20  No: 38273

Streamはさみ様、jazzin様、どうもありがとうございます。
ポインター、キャストなどの理解が必要のようですが色々調べながら見よう見まねでStringから個々のByteを得たりDoubleなどを切り出したりする方法が少しづつ分かってきて手がかりがつかめた気がします。またshortintとByteの違い、SmallintとWordの違い、LongintとLongWordの違いなどが分かってきました。

ReadBlockで受けた場合には一群のデータが分割して送られてきて、また頭(00)と尻尾(10+03)毎に区切られてきていませんがこれを一群ごとのデータとして区切れれば完成に近づくと思いますので現在これに取り組んでいます。時間が掛かってしまいお礼が遅くなって失礼しました。


みずき  2010-04-22 01:52:46  No: 38274

皆様ありがとうございました。
前回ご教示いただいた方式を真似て一群のデータ配列が切り出せればSmallint,Longint,文字列などが表示できることが分かりました。ReadBlockで受けた場合は細切れデータのため一群にまとめ、またそこから区切りを探して切り出す方法が分からずに苦労しましたがやっと完成しました。改めて御礼申し上げます。

(これ以降、別の質問を立てたほうが良いかもしれませんが今回の質問がCommXということで教えてください)

別のプロシージャから現在のバッファー残量を監視したいのでが、もしもVBのInBufferCountに相当するようなものがあったら教えてください。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加