Ver Mensaje Individual
  #2 (permalink)  
Antiguo 31/05/2014, 13:35
vosk
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: Sockets entre Java y C++

Envias el string con la funcion send:

Código C++:
Ver original
  1. int tlen, nbs;
  2. string texto;
  3.  
  4. texto = "un ejemplo";
  5. tlen = texto.length();
  6.  
  7. nbs = send(ConnectSocket, texto.c_str(), tlen, 0);

Y recibes datos con recv:

Código C++:
Ver original
  1. int nbr;
  2. char buffer[100];
  3.  
  4. nbr = recv(ConnectSocket, buffer, sizeof(buffer), 0);

Una cosa a tener en cuenta: mientras que para enviar puedes convertir los tipos string a char*, para recibir necesariamente debes tener reservado un bloque de memoria (ya sea con char* o con void*, pero no con string.c_str()).

Otra cosa a tener en cuenta: ambas funciones pueden no ejecutar la accion completa, es decir, si envias un string de 4000 caracteres puede que al primer intento solo envie 1000. Esto significa que debes prestar atencion al valor de retorno de la funcion send (en el ejemplo 'nbs'), que te indica el nº de bytes del buffer proporcionado que pudieron ser enviados; si no puede enviarlos todos, tienes que ejecutar otra vez el send pero omitiendo los caracteres enviados y volver a comprovar el nº de bytes enviados, y en caso necesario volver a repetir.

Lo mismo para recv: la funcion del servidor de java hará automaticamente lo que te comente del send (en java siempre viene todo implementado, pero de forma transparente para el programador hará las comprovaciones de bytes enviados y bytes pendientes), pero el cliente en c++ no sabe cuantos datos le envia el servidor porque el send puede implicar uno o mas envios. Para eso estan los protocolos. P.ej. el protocolo http define una cabecera con lineas de informacion terminadas con \r\n, a la vez que la cabecera finaliza con otro \r\n:

Código C:
Ver original
  1. dato1\r\n
  2. dato2\r\n
  3. \r\n

Esto implica que el cliente necesariamente ejecutará recv hasta que reciba \r\n\r\n. Esto es solo la parte superficial de http, te lo he comentado a modo de ejemplo, pero si te interesa puedes buscar mas informacion por ahi, o preguntar aqui mismo :) Puedes definir tu propio protocolo como transmisiones de texto finalizadas con la serie "qwerty", de forma que el servidor enviará el texto seguido de "qwerty" (independientemente de si requiere hacer una o mas llamadas send para completar el envio), entonces el cliente ejecutará recv tantas veces como sea necesario hasta que haya recibido la terminacion "qwerty", luego simplemente descartará la terminacion y ya tendrá el texto valido. Tambien puedes arriesgarte a suponer que todas las transmisiones se ejecutan a la primera y omotir lo del protocolo, esto depende de ti y de la fiabilidad que quieres que tenga tu aplicacion.

Con esto quiero que veas que aunque el servidor envie "una prueba de texto" el cliente no sabe cuando debe parar de leer. Tienes que implementar algun tipo de protocolo, por simple que sea.

Aun otra cosa: la funcion recv retorna el nº de bytes copiados al buffer proporcionado, pero el buffer proporcionado contendrá datos basura (y mas aun cuando ejecutes el recv dentro de un ciclo). Para asegurarte que te quedas solo con los datos recibidos tienes que truncar el buffer al nº de bytes recibidos:

Código C:
Ver original
  1. int nbr;
  2. char buffer[100];
  3.  
  4. if((nbr = recv(ConnectSocket, buffer, sizeof(buffer), 0)) < sizeof(buffer) {
  5.     buffer[nbr] = '\0';
  6. }

Hay mas formas de truncar el buffer, usa la que mas te guste.


"...A ser posible no querría tocar el código en Java..."

No, el servidor corre por una parte, el cliente por otra aun cuando esten en la misma maquina. Eso si, si debes implementar algun tipo de protocolo tendras que tocar el servidor.

Espero que te sea de ayuda
Saludos
vosk

Última edición por vosk; 31/05/2014 a las 13:51