2011-11-07 9 views
1

私のプログラムでは、java nioを使用しているため、10 KBのメッセージを連続して書き込もうとすると、socketchannel.write()は非常に遅くなります。完全な10KBメッセージを書き込むために測定された時間は、160msと200msの間です。しかし、完全な5KBメッセージを書き込む時間はわずか0.8msかかる。メッセージサイズが大きいとsocketchannel.write()が非常に遅くなる

セレクタでは、Selection.OP_READのみを持ち、Selection.OP_WRITEは処理しません。大きな完全なメッセージが受信されると、それは別の受信機に4回書き込まれます。

誰かが同じ問題を抱えていますか? socketchannel.write()についての投稿は遅いです。私の質問は、OP_READとOP_WRITEの間で交互に変更する方法です。

たとえば、150ミリ秒などの不確かさを追加すると、応答時間が短縮されます。バッファがいっぱいになったときに見つける方法はありますか?そうすれば、プログラムが待機するようにすることができます。私のオペレーティングシステムはWindows XPです。

ありがとうございました。

書いたバイト数をチェックしてEPJの提案に従います。しかし、応答時間はまだ高いです。私はここに私のコードの一部を投稿し、私のコードに間違いがあるかどうか調べたいと思っています。

//これはNIOを使用して書き込みデータ()一部です:

 while (buffer.hasRemaining()) { 
     try {   
       buffer.flip();     
       n = socket.write(buffer);   
       if(n == 0) {     
        key.interestOps(SelectionKey.OP_WRITE); 
        key.attach(buffer);    
        break; 
       }        
     } catch (IOException e) {    
      e.printStackTrace(); 
     } finally { 
      buffer.compact(); 
     } 
    } 

    if(buffer.position()==0) {     
     key.interestOps(SelectionKey.OP_READ); 
    } 
+0

私は多くのことを失敗した10キロバイトの1つのTCPパケットを送信するために恒久的にしようとしていると思います。 –

+0

メッセージは連続して発行されます。トポロジは一連のノードです。メッセージの間隔は100 msです。 – susan

+1

@MartijnCourteaux No. TCPパケット化は、より低いレベルで発生します。 IPパケット>経路MTUを送信しようとはしません。 – EJP

答えて

1

書き込みは20以上のマイクロ秒を要した場合、私はあなたがバッファフルの問題を持ってお勧めします。私はあなたがブロックNIOを使用していると仮定します。送信バッファがいっぱいでない場合、通常は5〜20マイクロ秒がかかります。過去に私はサーバーを構成して、遅い消費者を殺すために2ミリ秒かかりました。

SocketChannelsでも利用可能な送信バッファ(Socket.setSendBufferSize(int))のサイズを増やすことはできますが、より多くのデータを送信しようとしているように見えますあなたの帯域幅が許す。

10 KBは大きなメッセージではありません。典型的な送信バッファサイズは64 KBです。したがって、フルになるには、6-7個のメッセージを送信しなくてはなりません。これは、5KBが比較的速い方法を説明するかもしれません。

+0

ありがとうございます。しかし、私はJava非ブロックソケットを使用しています。サーバーはメッセージを受信すると、それを次のホップに4回転送します。私は選択キーをOP_WRITEに変更しません。選択キーを書くときはOP_READです。私の問題は、TCPバッファがいっぱいだと思います。私の推測が正しければ、この問題をどのように修正するのですか? socketchannelをシャットダウンすると便利でしょうか? – susan

+0

なぜ帯域幅が不足しているのか、低速の消費者がいないのかを判断して修正すると便利です。いずれかを制御できない場合は、ソケットを閉じることが最後の手段です。 BTW:ノンブロッキングを使用している場合は、書き込み時にブロックすべきではありません。データの書き込みに失敗する必要があります。 –

3

読み取りプロセスが遅く、受信バッファがバックアップする原因になっていることが考えられます。これは送信バッファをバックアップして送信を停止します。

または、ノンブロッキングモードでコードを正しく書いていない。 write()メソッドからゼロの結果が得られた場合は、(a)interestOpsをOP_WRITEに変更し、(b)selectループに戻ります。 OP_WRITEを取得すると、書き込みを繰り返す必要があります。すべてのデータを書き込んだ場合は、interestOpsをOP_READに戻し、そうでない場合はすべてをそのままにして、次のOP_WRITEを待ちます。長さ0の書き込みがあってもノンブロッキングモードで書き込み中にループしようとすると、CPUサイクルと時間を無駄にするだけです。

モジュロのバグ:

while (buffer.position() > 0) 
{ 
    try 
    { 
    buffer.flip(); 
    int count = ch.write(buffer); 
    if (count == 0) 
    { 
     key.interestOps(SelectionKey.OP_WRITE); 
     break; 
    } 
    } 
    finally 
    { 
    buffer.compact(); 
    } 
} 
if (buffer.position() == 0) 
{ 
    key.interestOps(SelectionKey.OP_READ); 
} 
+0

@susanあなたは全く新しい登録をしています。私はinterestOpsをOP_WRITEに変更するように言いました。あなたが書き込みに成功するとOP_READに戻すように言いました。あなたはそれをやっていません。別の問題は、書き込み状態にかかわらずflip()とwrite()の後に*常に* compact()する必要があることです。そうでなければ、バッファは無効な状態のままです。もう一つは、write()が<0を返さないことです:Javadocを見てください。 – EJP

+0

サンプルコードがある場合は、非常に役立ちます。 WindowsシステムのTCPバッファを変更すると便利ですか? – susan

+0

@susan上記を参照してください。 Windowsソケットの送受信バッファは、8kではあまりにも小さすぎることが知られており、32kまたは48kにバンプすると常に役立ちます。しかし、私はあなたがコーディングの問題を抱えていると信じています。 – EJP

関連する問題