2012-01-06 44 views
6

Tôi gặp sự cố với chương trình của mình khi tôi cần gửi Chuỗi từ cổng bluetooth máy chủ đến ổ cắm bluetooth của khách hàng của mình. Mọi thứ hoạt động tốt miễn là tôi chỉ gửi một chuỗi tại một thời điểm (ví dụ như trò chuyện) nhưng nếu tôi cần viết nhiều chuỗi hơn trong một khoảng thời gian ngắn (để trao đổi thông tin), các chuỗi sẽ không bị tách khỏi máy khách mã. Ví dụ nếu tôi đang gửi "FirstUser" và ngay sau đó "SecondUser" khách hàng không đọc "FirstUser" và sau đó "SecondUser". Nó sẽ đọc "FirstUserSecondUser". Làm cách nào để tránh hành vi này?Kết nối Bluetooth; không thể gửi các chuỗi đúng cách

Chỉnh sửa: Nếu tôi để Chủ đề ngủ trước khi có thể gửi tin nhắn mới, nó đọc đúng chuỗi nhưng giải pháp này không hoạt động tốt cho nhu cầu của tôi.

Server-Code: gửi tới tất cả khách hàng (edited)

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"); 
     } 
    } 
} 

Server-Code: đọc từ một khách hàng:

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(); 
      } 
    } 
} 

Client-Code: đọc từ máy chủ (chỉnh sửa)

@Override 
    protected Void doInBackground(Integer... ints) {  
     String nachricht = new String(); 
     byte[] buffer = new byte[1024]; 
     int numRead; 
     while (runningFlag) 
     { 
      try { 
       if(((numRead = inputStream.read(buffer)) >= 0)) { 
        nachricht = new String(buffer, 0, numRead); 
        publishProgress(nachricht); 
       } 
      } 
      catch (IOException e) { 
       clientGame.finish(); 
       e.printStackTrace(); 
      }      
     } 
     return null; 
} 

Mã khách hàng: viết thư đến máy chủ

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(); 
     } 
    } 

Tôi đánh giá cao mọi trợ giúp nhỏ :).

+0

Máy chủ của bạn có gửi tin nhắn cho khách hàng hoặc ngược lại không? –

+0

Cả hai cách 'tròn'. Tôi tạm thời "giải quyết" vấn đề với Thread.sleep (100) trước khi máy khách hoặc máy chủ có thể gửi một chuỗi khác. Nhưng đó không thực sự là một giải pháp gọn gàng. – Refrigerator

+0

bạn có đang xóa tất cả các tin nhắn đã gửi không? –

Trả lời

8

Bạn cần đóng gói mục dữ liệu của mình để tránh ghép nối. Điều đó có nghĩa là bạn phải viết và đọc toàn bộ mục dữ liệu trước khi tiếp tục.

Bạn nên có một số phương pháp hữu ích để làm điều đó thay vì trực tiếp sử dụng phương pháp OutputStream và 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); 
} 

Sau đó, bạn sử dụng các phương pháp này cho cả máy chủ & khách hàng để đọc và viết mục Chuỗi của bạn.

+0

Về tài liệu của OutputStream.flush() nói rằng "Việc triển khai này không làm gì cả." nó là bình thường bởi vì OutputStream chỉ là một lớp trừu tượng. Lớp thực tế (FileOutputStream, SocketOutputStream, ...) ghi đè phương thức này để làm điều gì đó. –

+0

Tôi không thể hiểu mã của bạn. Bạn có thể thử giải thích nó không? ví dụ tôi chưa bao giờ thấy các toán tử '>>>' và '| =' trước đây. Và tại sao có một nối? Tại sao flush() không giải quyết được vấn đề? – Refrigerator

+0

Lệnh flush() không thể bảo hành thời gian bạn nhận dữ liệu vì bạn đang sử dụng socket và có nhiều bộ đệm trung gian giữa các lớp và hệ thống OSI. –

Các vấn đề liên quan