c++ - que - pipes programacion
Determine el tamaño de una tubería sin llamar a read() (12)
Necesito una función llamada SizeOfPipe () que devuelva el tamaño de una tubería. Solo quiero saber cuántos datos hay en la tubería y no leer datos de la tubería en sí.
Pensé que el siguiente código funcionaría
fseek (pPipe, 0 , SEEK_END);
*pBytes = ftell (pPipe);
rewind (pPipe);
pero dosent fseek trabaja en descripciones de archivos. Otra opción sería leer el conducto y luego volver a escribir los datos, pero me gustaría evitar esto si es posible, ¿alguna sugerencia?
Casi nunca es necesario saber cuántos bytes hay en la tubería: quizás solo quiera hacer una lectura no bloqueante () en la tubería, es decir. para verificar si hay algún número listo, y si es así, léalos, pero nunca se detenga y espere a que el conducto esté listo.
Puedes hacer eso en dos pasos. Primero, use la llamada al sistema select () para averiguar si los datos están disponibles o no. Un ejemplo está aquí: http://www.developerweb.net/forum/showthread.php?t=2933
Segundo, si select indica que los datos están disponibles, llame a read () una vez, y solo una vez, con un tamaño de bloque grande. Solo se leerán tantos bytes disponibles, o hasta el tamaño de su bloque, el que sea más pequeño. Si select () devuelve true, read () siempre regresará de inmediato.
Algunas implementaciones de UNIX devuelven la cantidad de bytes que se pueden leer en el campo st_size
después de llamar a fstat()
, pero esto no es portátil.
Dependiendo de su implementación de UNIX ioctl / FIONREAD podría hacer el truco
err = ioctl(pipedesc, FIONREAD, &bytesAvailable);
A menos que esto devuelva el código de error para "argumento inválido" (o cualquier otro error) bytesAvailable contiene la cantidad de datos disponibles para desbloquear operaciones de lectura en ese momento.
Desafortunadamente, el sistema no siempre puede conocer el tamaño de una tubería; por ejemplo, si está conectando un proceso de larga ejecución a otro comando, es posible que el proceso de origen no haya finalizado aún. En este caso, no hay forma posible (incluso en teoría) de saber cuánto más información va a salir de ella.
Si desea conocer la cantidad de datos actualmente disponibles para leer fuera de la red, podría ser posible, pero dependerá del almacenamiento en búfer del SO y de otros factores que son difíciles de controlar. El enfoque más común aquí es simplemente seguir leyendo hasta que no quede nada por venir (si no obtiene un EOF, entonces el proceso de origen no ha terminado aún). Sin embargo, no creo que esto sea lo que estás buscando.
Entonces, me temo que no hay una solución general.
En general, no es posible saber la cantidad de datos que puede leer de una tubería solo desde la manija de la tubería. Los datos pueden estar ingresando a través de una red, o generados dinámicamente por otro proceso. Si necesita saber de antemano, debe hacer los arreglos para que le envíen la información, a través de la tubería o fuera de banda, mediante cualquier proceso que se encuentre en el otro extremo de la tubería.
No creo que sea posible, el objetivo de una tubería no es proporcionar comunicación entre los dos extremos (en una dirección). Si estoy en lo correcto en esa afirmación, es posible que el envío aún no haya terminado de enviar datos a la tubería, por lo que sería imposible determinar la duración.
¿Qué plataforma estás usando?
No creo que sea posible. Las tuberías presentan un protocolo orientado a flujo en lugar de uno orientado a paquetes. IOW, si escribe en un tubo dos veces, una vez con, por ejemplo, 250 bytes y una vez con, digamos, 520 bytes, no hay manera de decir cuántos bytes obtendrá del otro extremo en una solicitud de lectura. Podría obtener 256, 256 y luego el resto.
Si necesita imponer paquetes en un conducto, debe hacerlo usted mismo escribiendo número de bytes predeterminado (o delimitado) como longitud de paquete, y luego el resto del paquete. Use select () para averiguar si hay datos para leer, use read () para obtener un búfer de tamaño razonable. Cuando tienes tu buffer, es tu responsabilidad determinar el límite del paquete.
No hay una forma genérica y portátil de saber cuántos datos hay disponibles en una tubería sin leerlos. Al menos no bajo las especificaciones POSIX.
Las tuberías no son buscables, y tampoco es posible volver a colocar los datos en el extremo de lectura de una tubería.
Trucos específicos de plataforma podrían ser posibles, sin embargo. Si su pregunta es específica de la plataforma, edite su pregunta para decirlo, lo que podría mejorar sus posibilidades de obtener una respuesta funcional.
No hay una forma portátil de contar la cantidad de datos que provienen de una tubería. Lo único que podrías hacer es leer y procesar los datos tal como vienen.
Para eso podrías usar algo así como un buffer circular
Si desea saber la cantidad de datos que se espera que llegue, siempre puede escribir al comienzo de cada mensaje enviado por las tuberías el tamaño del mensaje. Así que escriba, por ejemplo, 4 bytes al comienzo de cada mensaje con la longitud de sus datos, y luego solo lea los primeros 4 bytes.
Puede envolverlo en objetos con almacenamiento en búfer que se puede rebobinar. Esto sería factible solo para pequeñas cantidades de datos.
Una forma de hacerlo en C es definir stuct y ajustar todas las funciones que operan en las tuberías para su estructura.
En Windows siempre puedes usar PeekNamedPipe
, pero dudo que sea lo que quieras hacer de todos modos.