2009-08-21 15 views
5

Actualmente estoy escribiendo una aplicación en Blackberry para enviar y recibir datos en bruto a otro dispositivo TCP en mi red. Estoy teniendo el mismo problema en el simulador de Blackberry con un simulador MDS funcionando y usando un teléfono físico que habla con el servidor MDS de mi compañía. Tenga en cuenta que este problema no ocurre cuando se usa wifi directamente y no a través de MDS.Problema al usar SocketConnection con Blackberry usando MDS

El problema es que la función disponible() en InputStream devuelve cero a menos que llame primero a read(). Si llamo a leer primero (sabiendo que hay algunos datos disponibles ... gracias wireshark) los datos vuelven, y la llamada subsiguiente a disponible() indica qué datos quedan que no he leído. El problema es que no siempre se me garantizará que los datos estén allí y que pueda bloquearlos. ¿Alguien es consciente de esto? ¿Es esto un problema o algo por diseño?

¿Alguien conoce una forma de probar si el (los) método (s) de lectura (s) se bloquearán antes de llamarlos aparte de los disponibles?

Aquí es básicamente lo que estoy haciendo:

 
SocketConnection s = (SocketConnection)Connector.open("socket://1.2.3.4:port;deviceside=false", Connector.READ_WRITE); 

OutputStream o = ((StreamConnection)s).openOutputStream(); 
InputStream i = ((StreamConnection)s).openInputStream(); 

o.write("hello"); 
Thread.sleep(sometime); 
if (i.available() > 0) { 
    byte[] data = new data[10]; 
    int bytesRead = i.read(data); 
    System.out.println("Read [" + new String(data) + "] (bytes = " + bytesRead + ")"); 
} 

tengo que comentar el caso condicional para que esto funcione.

+0

Podría bloquear, pero ¿es un problema si su red está en un hilo separado? – lilbyrdie

+0

Creo que he leído en algún lugar de los documentos que este es el comportamiento especificado que está disponible. Como dice Libyrdie, los hilos son tu amigo. Giro un hilo para hacer la lectura y simplemente dejo que se bloquee. – Richard

+0

Normalmente eso estaría bien.El problema es que estamos tratando de averiguar si un dispositivo está presente u operando correctamente al ver si responde a un ping TCP específico. Solo permitir leer para bloquear no ayuda mucho. Básicamente tenemos que engendrar el hilo y luego matarlo después de X segundos. Esto no es muy difícil, pero no es ideal. Esto no sería tan frustrante si esto no funcionara al usar Wifi directo en lugar de una conexión MDS. Si usa WiFi directo, funciona muy bien. – borq

Respuesta

0

Como indiqué en un comentario anterior, necesitaba una forma de determinar si un dispositivo al que me estoy conectando no está allí, y lo hago ver si nuestro 'ping' devuelve datos. Si el dispositivo no está allí, bloqueará. No puedo confiar en ese comportamiento. Otro problema que surgió al resolver esto es que los métodos de lectura (...) de la clase RIM InputStream bloquean si proporciona un búfer más grande que los datos que desea recuperar. ¿Pero cómo se supone que sé cuántos datos hay si está disponible() devuelve 0? Leer byte a byte es la única forma de hacerlo, pero aún bloquea si no hay datos.

Para resolver esto seguí el tema de la primera respuesta, pero puse este método en su propio hilo y lo escribí en un búfer de bytes separado. Creé una clase que amplió InputStream e implementó available() y read (...). Los retornos disponibles indican cuántos bytes hay en el búfer de bytes, y la lectura solo devuelve todo lo que hay en el búfer o lo que solicite el llamador, lo que sea menor.

Esta configuración me permite usar una interfaz InputStream, pero detrás de escena solo está funcionando continuamente un hilo lector que está vivo hasta que se corta la conexión. En ese momento, la lectura, si está bloqueada, arrojará una excepción para indicar que la conexión está cerrada. Este comportamiento está bien ya que se puede manejar fácilmente.

Gracias a todos los que ayudaron con este problema. Tus pensamientos ayudan a avanzar hacia la solución.

3

El contrato general del método InputStream.available() es que "Devuelve el número de bytes que se pueden leer (o omitir) de esta corriente de entrada sin bloqueo por la siguiente persona que llama de un método para esta corriente de entrada " Por lo tanto, en la mayoría de las implementaciones, no es garantía de que devolverá la Longitud del contenido de la transmisión que se está leyendo. Por lo tanto es mejor leerlo de la siguiente manera

byte[] readFromStream(InputStream is) throws IOException 
{ 
    byte[] data = new byte[4096]; 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    DataOutputStream dos = new DataOutputStream(baos); 

    int count = is.read(data, 0, data.length); 
    while (count != -1) 
    { 
     dos.write(data, 0, count); 
     count = is.read(data, 0, data.length); 
    } 

    data = baos.toByteArray(); 

    return data; 
} 

Llamar al método ReadFromStream() y obtener el byte [] regresó.

+0

Exactamente. Lo mismo en Android. – yanchenko

Cuestiones relacionadas