蓝牙连接;无法正确发送字符串

问题描述:

当我需要从服务器的蓝牙套接字发送字符串到我的客户端的蓝牙套接字时,我遇到了麻烦。 一切正常,只要我一次只发送一个字符串(例如聊天),但如果我需要在短时间内写入更多的字符串(以交换信息),则字符串不会与客户端分离码。例如,如果我发送“FirstUser”,并在此之后“SecondUser”,客户端不会读取“FirstUser”,然后读取“SecondUser”。它会读取“FirstUserSecondUser”。我怎样才能避免这种行为?蓝牙连接;无法正确发送字符串

编辑:如果让线程在能够发送新消息之前先休眠,它会读取正确的字符串,但此解决方案无法正常工作以满足我的需要。

服务器的代码:发送到所有客户端(编辑)

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

客户代码:从服务器读取(编辑)

@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; 
} 

客户代码:写入服务器

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

您的服务器是否向客户端发送消息,反之亦然? – 2012-01-06 13:30:13

+0

两种方式。在客户端或服务器能够发送另一个字符串之前,我暂时用Thread.sleep(100)“解决”了问题。但这不是一个很好的解决方案。 – Refrigerator 2012-01-06 16:28:46

+0

你是否冲洗所有发送的消息? – 2012-01-06 16:30:35

您需要封装您的数据项以避免串联。 这意味着您必须在继续之前编写和读取整个数据项。

你应该有一些实用的方法来做到这一点,而不是直接使用的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,...)会覆盖此方法来执行某些操作。 – 2012-01-13 15:32:32

+0

我无法理解你的代码。你可以试着解释一下吗?例如我从来没有见过'>>>'和'| ='操作符。 为什么会有连接?为什么flush()不能解决问题? – Refrigerator 2012-01-13 17:28:28

+0

由于使用套接字,flush()不能保证您接收数据的时间,并且在OSI图层和系统之间有多个中间缓冲区。 – 2012-01-13 17:36:37