2012-01-06 8 views
6

サーバのBluetoothソケットからクライアントのBluetoothソケットに文字列を送信する必要があるときに、プログラムに問題があります。 私は一度に1つのString(例えばチャット)を送信している間はすべてうまく動作しますが、短期間に(情報を交換するために)より多くのStringを書き込む必要がある場合、文字列はクライアントから分離されませんコード。たとえば、「FirstUser」を送信していて、その「SecondUser」の直後にクライアントが「FirstUser」と「SecondUser」を読み取っていないとします。 "FirstUserSecondUser"が読み込まれます。どうすればこの問題を回避できますか?Bluetooth接続。文字列を正しく送ることができない

編集:新しいメッセージを送信する前にスレッドをスリープ状態にすると、正しい文字列が読み込まれますが、この解決策は必要な場合にはうまく機能しません。

サーバー・コード:(編集済み)すべてのクライアントに送信

public synchronized void sendToAll(String message) 
{ 
    try { 
     Thread.sleep(100); 
    } catch (InterruptedException e1) { 
     e1.printStackTrace(); 
    } 

    publishProgress(message); 
    for(OutputStream writer:outputList) { 
     try { 
      writer.write(message.getBytes()); 
      writer.flush(); 
     } catch (IOException e) { 
      System.out.println("Some-Error-Code"); 
     } 
    } 
} 

サーバー・コード:クライアントからの読み込み:

public void run() { 
    String nachricht; 
    int numRead; 
    byte[] buffer = new byte[1024]; 
    while (runningFlag) 
    { 
     try { 
      if((numRead = inputStream.read(buffer)) >= 0) { 
       nachricht = new String(buffer, 0, numRead); 
       serverThread.handleMessage(nachricht); 
      } 
      } 
      catch (IOException e) { 
       this.cancel(); 
       e.printStackTrace(); 
      } 
    } 
} 

クライアントコード:サーバーからの読み込み(編集済み)

クライアントコード:サーバーへの書き込み

public synchronized void write(String nachricht) 
    { 
     try { 
      Thread.sleep(100); 
     } catch (InterruptedException e1) { 
      e1.printStackTrace(); 
     } 

     try { 
      outputStream.write(nachricht.getBytes()); 
      outputStream.flush(); 
     } catch (IOException e) { 
      this.cancel(); 
      e.printStackTrace(); 
     } 
    } 

私はすべての小さな助けを感謝します:)。

+0

サーバーはクライアントにメッセージを送信しますか、またはその逆ですか? –

+0

両方のラウンド。クライアントまたはサーバが別の文字列を送信する前に、Thread.sleep(100)の問題を一時的に「解決」しました。しかし、それは本当にすてきな解決策ではありません。 – Refrigerator

+0

送信したすべてのメッセージを消去していますか? –

答えて

8

連結を避けるためにデータ項目をカプセル化する必要があります。 これは、続行する前にデータ項目全体を読み書きする必要があることを意味します。

代わりに、直接のOutputStreamとInputStreamのメソッドを使用してのことを行うには、いくつかのユーティリティメソッドを持つ必要があります

public static void writeItem(OutputStream out, String s) throws IOException 
{ 
    // Get the array of bytes for the string item: 
    byte[] bs = s.getBytes(); // as bytes 
    // Encapsulate by sending first the total length on 4 bytes : 
    // - bits 7..0 of length 
    out.write(bs.length);  // modulo 256 done by write method 
    // - bits 15..8 of length 
    out.write(bs.length>>>8); // modulo 256 done by write method 
    // - bits 23..16 of length 
    out.write(bs.length>>>16); // modulo 256 done by write method 
    // - bits 31..24 of length 
    out.write(bs.length>>>24); // modulo 256 done by write method 
    // Write the array content now: 
    out.write(bs); // Send the bytes 
    out.flush(); 
} 

public static String readItem(InputStream in) throws IOException 
{ 
    // first, read the total length on 4 bytes 
    // - if first byte is missing, end of stream reached 
    int len = in.read(); // 1 byte 
    if (len<0) throw new IOException("end of stream"); 
    // - the other 3 bytes of length are mandatory 
    for(int i=1;i<4;i++) // need 3 more bytes: 
    { 
     int n = in.read(); 
     if (n<0) throw new IOException("partial data"); 
     len |= n << (i<<3); // shift by 8,16,24 
    } 
    // Create the array to receive len bytes: 
    byte[] bs = new byte[len]; 
    // Read the len bytes into the created array 
    int ofs = 0; 
    while (len>0) // while there is some byte to read 
    { 
     int n = in.read(bs, ofs, len); // number of bytes actually read 
     if (n<0) throw new IOException("partial data"); 
     ofs += n; // update offset 
     len -= n; // update remaining number of bytes to read 
    } 
    // Transform bytes into String item: 
    return new String(bs); 
} 

は、次に、あなたの文字列のアイテムを読み書きするために、両方のサーバー&クライアントのためにこれらのメソッドを使用します。

+0

OutputStream.flush()のドキュメントについて "この実装は何もしません" OutputStreamは抽象クラスなので正常です。実際のクラス(FileOutputStream、SocketOutputStream、...)は、このメソッドをオーバーライドして何かを行います。 –

+0

あなたのコードを理解できません。あなたはそれを説明しようとすることができますか?たとえば、私は前に '>>>'と '| ='演算子を見たことがありません。 なぜ連結はありますか?なぜflush()は問題を解決しないのですか? – Refrigerator

+0

ソケットを使用しており、OSIのレイヤーとシステムの間に複数の中間バッファーがあるため、flush()はデータを受け取る時間を保証することができません。 –

関連する問題