Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - fekaa30

#1
Java / Duda con sockets en java
8 Octubre 2012, 00:29 AM
Buenos días.

Tengo una duda que me está carcomiendo la cabeza: Intento hacer una aplicación cliente servidor, desde el servidor espero conexiones (es un servidor que acepta varios clientes).

La cuestion es que yo quiero realizar algo como lo siguiente:

-> Esperar conexión en el servidor
  -> Cliente conectado
-> Obtener socket del cliente con server.accept();
-> Abrir flujos DataInputStream y DataOutputStream del socket
-> Enviar un paquete al cliente, para ello uso DataOutputStream
  -> Recibir paquete del servidor, para ello uso DataInputStream
  -> Enviar respuesta al servidor
-> Recibir respuesta del cliente
-> Enviar paquete al cliente
  -> Recibir paquete del servidor, para ello vuelvo a usar DataInputStream
  -> Enviar paquete al servidor
-> Recibir paquete del cliente
-> Cerrar conexion

Bien, como pueden ver no es algo muy complicado ya que de ésa manera tengo entendido que funcionan los sockets (según lo que leí). La comunicación la hago en binario (osea, transmito y recibo paquetes pero no en formato texto, no se si me explico).

Mi problema es el siguiente: Cuando envío el primer paquete al cliente, me lo transmite correctamente. Luego, desde el cliente le respondo al servidor, quien recibe correctamente el paquete. Pero luego quiero enviar un nuevo paquete desde el servidor al cliente, y me dice que el Socket ya ha sido cerrado. Para enviar datos al cliente por el socket uso el método write(byte[] data) de DataOutputStream. Luego hago un dOutputStream.close(); (haciendo ésto es cuando me llegan los datos correctos al cliente). Pero se vé que cuando cierro el flujo de salida, no puedo enviar más nada.

Ésto es lo que tengo en el método run del ServerSocketThread

Código (java) [Seleccionar]
public void run(){

int maxLen = 1024;
byte[] buffer; //Buffer de datos

while(true){
try {
dInputStream  = new DataInputStream(socket.getInputStream());
dOutputStream = new DataOutputStream(socket.getOutputStream());
//Leemos el paquete, y de aqui lo mandamos a analizar.
buffer = new byte[maxLen]; //Definimos el buffer con el tamaño maximo de 1024 bytes
int k = -1;
int readLen = 0;

while((k = dInputStream.read()) != -1 && readLen < maxLen){ //Leemos byte a byte hasta que no queden mas bytes
buffer[readLen] = (byte)k;
readLen++;
if(k == ConstantsProtocol.END)
break;
}

//Si recibimos menos del maximo, entonces lo guardaremos en un arreglo nuevo para que no queden espacios vacios (0x00)
if(readLen <= maxLen){
byte[] buffAux = new byte[readLen];
ByteUtils.arrayCopy(buffer, 0, buffAux, 0, readLen);
buffer = buffAux;
}

Print.logInfo("Recv[" + readLen + "][Hex]: " + StringTools.toHexString(buffer));
byte respuesta[] = new byte[3];
respuesta[0] = 0x00;
respuesta[1] = 0x00;
respuesta[2] = 0x00;
dOutputStream.write(respuesta);
dOutputStream.close();
} catch(SocketTimeoutException timeout){
Print.logError("Read timeout[30s]: Cerrando conexion");
try {
socket.close();
Print.logError("Conexion cerrada.");
break;
} catch (IOException e) {
Print.logError("Error al cerrar conexion por timeout: " + e.getMessage());
} catch (Throwable e) {
Print.logError("Error al cerrar Thread por timeout: " + e.getMessage());
}
} catch (IOException e) {
Print.logError("Error al leer: " + e.getMessage());
break;
}
}
}


Gracias, espero puedan ayudarme.

saludos!
#2
Buenas noches.

Estuve leyendo el problema, te explico mas o menos los datos que podés obtener para poder lograr algo:

La clase DataInputStream que estás usando, es conveniente para guardar datos primitivos (por ejemplo, enteros en tu caso). Según he comprobado, una vez que comenzas a leer los datos, esos datos desaparecer de la memoria de ese objeto. El método available() de la clase DataInputStream permite obtener los bytes disponibles a leer. Cada entero que guardes en un archivo con la clase DataOutputStream, ocupa 4 bytes: ésto significa que si hacemos un (DataInputStream.available() / 4); obtenemos el número de enteros a leer de dicho archivo en memoria. Sin usar arreglos, se complica demasiado; aún así, una solución que se me ocurre es usar una lista enlazada simple de enteros, e ir guardando allí todos los datos. Luego, usas un algoritmo de ordenamiento de listas y la recorres guardando en el archivo MEZCLA.dat los numeros obtenidos (en forma ordenada).

Si no, se me ocurre otra solución, pero es muy "negra" (poco eficiente en mi lenguaje). Si lo solucionas, me avisas cómo lo hiciste, y si se te ocurre alguna idea coméntala así podremos analizarla juntos.

Saludos