2012-01-06 14 views
6

Tengo problemas con mi programa cuando necesito enviar cadenas desde mi servidor bluetooth-socket a mi cliente bluetooth-socket. Todo funciona bien siempre que envíe solo una cadena a la vez (por ejemplo, chat) pero si necesito escribir más cadenas en un corto período de tiempo (para intercambiar información), las cadenas no se separarán del cliente código. Por ejemplo, si estoy enviando "FirstUser" y justo después de "SecondUser", el cliente no lee "FirstUser" y luego "SecondUser". Se leerá "FirstUserSecondUser". ¿Cómo puedo evitar este comportamiento?conexión Bluetooth; no puedo enviar cadenas correctamente

Editar: Si dejo que el subproceso duerma antes de que pueda enviar un nuevo mensaje, se leerán las cadenas adecuadas, pero esta solución no está funcionando bien para mi necesidad.

servidor Código: enviar a todos los clientes (editado)

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

servidor Código: lectura de un cliente:

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

cliente-Code: leer desde el servidor (editado)

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

Código de cliente: escribiendo en el servidor

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

Aprecio cada pequeña ayuda :).

+0

¿Su servidor envía un mensaje a los clientes o viceversa? –

+0

En ambos sentidos 'ronda. Temporalmente "resolví" el problema con Thread.sleep (100) antes de que el cliente o servidor pueda enviar otra cadena. Pero esa no es realmente una buena solución. – Refrigerator

+0

¿Estás enjuagando todos los mensajes enviados? –

Respuesta

8

Debe encapsular su elemento de datos para evitar la concatenación. Significa que debe escribir y leer un elemento de datos completo antes de continuar.

Usted debe tener algunos métodos de utilidad para hacer que en lugar de utilizar directamente los métodos de OutputStream y 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); 
} 

continuación, utiliza estos métodos, tanto para el servidor & cliente para leer y escribir sus artículos de Cuerda.

+0

Acerca de la documentación de OutputStream.flush() que dice "Esta implementación no hace nada". es normal porque OutputStream es solo una clase abstracta. La clase real (FileOutputStream, SocketOutputStream, ...) anula este método para hacer algo. –

+0

No puedo entender tu código. ¿Puedes tratar de explicarlo? por ejemplo, nunca antes había visto los operadores '>>>' y '| ='. ¿Y por qué hay una concatenación? ¿Por qué flush() no resuelve el problema? – Refrigerator

+0

El flush() no puede garantizar el tiempo de recepción de datos porque está utilizando un socket, y hay varios buffers intermedios entre capas y sistemas OSI. –

Cuestiones relacionadas