- PR -

データの連続送受信に関して。

投稿者投稿内容
H2
ぬし
会議室デビュー日: 2001/09/06
投稿数: 586
お住まい・勤務地: 港
投稿日時: 2003-12-01 17:15
> なぜInputStream#read();を使わないのでしょうか?
さぁ?なぜでしょう?忘れました 使っても問題はありません。多分、readを使うともう一個whileループを書く必要があり、面倒だったからだったからだというような気がします。

> なぜ0-255の長さをそのまま1byteに格納しないのでしょうか?
    byte[] size = new byte[1]; //メッセージサイズは1バイト(0-255文字)
    in.read(size); //メッセージサイズがsize[0] に入る
としたのは、メッセージサイズが1byte分よりも大きくなるかもしれないからです。もし、メッセージの最大値が255バイト分よりも大きい場合は
    byte[] size = new byte[2]; //メッセージサイズは2バイト(0-65536文字)
    in.read(size); //メッセージサイズがsize[0]とsize[1] に入る
となります。もちろん、前述したようにread()を使ってもまったく問題はありません。

> in.read(message)が配列を満たすことなく返る場合がある事をお忘れではないでしょうか?
それはエラー時の場合ではないでしょうか?APIドキュメントによると、messageがフルになる、EOFが発見される、タイムアウトをする、もしくはIOExceptionが返された時です。メッセージがヘッダーにあるメッセージの長さよりも短くなることはありえないので、EOFはありえません。タイムアウトとIOExceptionは明らかにエラーです。エラーでもなく、タイムアウトでもなく、さらにEOFが発見されているわけでもないのにmessageが埋まらないという現象は記憶にありません。おきるのですか?

#追記.おお、そういえばおきてました。 かなり昔に自分で体験したのを忘れてました。 そうです、そうです。だからread()を使ってたんだ・・・。しかもAPIにも書いてあるし。。。安全を考えるならread()の方がいいですね。ということで、
    byte[] size = new byte[2]; //メッセージサイズは2バイト(0-65536文字)
    in.read(size); //メッセージサイズがsize[0]とsize[1] に入る
はsize[1]にデータが入らない可能性がありえるのでよくありません。



[ メッセージ編集済み 編集者: H2 編集日時 2003-12-02 06:35 ]

[ メッセージ編集済み 編集者: H2 編集日時 2003-12-02 06:38 ]
にとろ
会議室デビュー日: 2003/11/30
投稿数: 4
投稿日時: 2003-12-01 23:09
皆様多くのご意見ありがとうございます。

結局、クライアントごとのスレッド立てて、メッセージフォーマットの先頭にデータサイズを付与する形で落ち着きました。


以下クライアントスレッド作成ソース(未動作確認)
ソケットではなく、ソケットチャネルを使用しました。
また、エラー処理は省いてあります。
------------------------------------------------
// メインループ
while(true){

 int recSize = 0;
 int allRecSize = 0;

 // データサイズ分の領域を取得
 ByteBuffer byteBuffer = ByteBuffer.allocate(int);
 // データサイズbyte読み込みループ
 while(true){
  // 読み込み処理
  recSize = socketChannel.read(byteBuffer);
  // 読み込みデータサイズを算出
  allSize = allRecSize + size;
  // 取得した領域がint型4byte分だったら
  if(allSize == 4){
   break;
  }
 }

 // バイトポジションを0に戻す
 byteBuffer.position(0);
 // int型のデータサイズを取得
 int allDataSize = byteBuffer.getInt();

 recSize = 0;
 allRecSize = 0;

 // データサイズ分の領域を取得
 ByteBuffer allByteBuffer = ByteBuffer.allocate(int);
 // データ読み込みループ
 while(true){
  // 読み込み処理
  recSize = socketChannel.read(allByteBuffer );
  // 読み込みデータサイズを算出
  allRecSize = allRecSize + recSize;

  // データサイズだけ読み込んだ場合
  if(allRecSize == allDataSize){
   // スレッドプールへデータを渡す

  }
 }
}
-----------------------------------------------------------

しかし、気になるのは、速度の問題です・・・
ノンブロッキングモードでTCPの送受信を行った場合の受信方法をどなたかご存知ないでしょうか??



[ メッセージ編集済み 編集者: にとろ 編集日時 2003-12-02 01:05 ]
Keisuke
大ベテラン
会議室デビュー日: 2003/10/24
投稿数: 105
投稿日時: 2003-12-02 02:39
引用:

H2さんの書き込み (2003-12-01 17:15) より:
    byte[] size = new byte[1]; //メッセージサイズは1バイト(0-255文字)
    in.read(size); //メッセージサイズがsize[0] に入る


これは動きます。
引用:

    byte[] size = new byte[2]; //メッセージサイズは2バイト(0-65536文字)
    in.read(size); //メッセージサイズがsize[0]とsize[1] に入る


こちらは2バイト読み込まれる保障がないので危険です。
Keisuke
大ベテラン
会議室デビュー日: 2003/10/24
投稿数: 105
投稿日時: 2003-12-02 02:47
引用:

にとろさんの書き込み (2003-11-30 18:39) より:

・クライアントの送信間隔は高速(50〜500msec)である。


全く「高速」とは思いません。おそらく1メッセージの処理は 100usec のオーダーだと思います。

スキルアップ/キャリアアップ(JOB@IT)