socket sockaddr_in servidor example ejemplos cliente c sockets networking types header-files

sockaddr_in - ¿Dónde encontrar la definición completa del tipo off_t?



socket example java (4)

Estoy enviando archivos de cliente a servidor usando TCP. Para marcar el final del archivo, me gusta enviar el tamaño del archivo antes de los datos reales. Entonces utilizo la llamada al sistema stat para encontrar el tamaño del archivo. Esto es de tipo off_t . Me gusta saber cuántos bytes ocupa para que pueda leerlo correctamente en el lado del servidor. Se define en <sys/types.h> . Pero no entiendo la definición. Simplemente define __off_t or _off64_t para estar off_t . Dónde buscar __off_t ? También es una convención que __ tiene el prefijo para la mayoría de las cosas en los archivos de encabezado y me asusta cuando leo los archivos de encabezado para comprender mejor. ¿Cómo leer un archivo de cabecera mejor?

#ifndef __off_t_defined # ifndef __USE_FILE_OFFSET64 typedef __off_t off_t; # else typedef __off64_t off_t; # endif # define __off_t_defined #endif


Como dice el "Manual de referencia de la biblioteca GNU C"

off_t This is a signed integer type used to represent file sizes. In the GNU C Library, this type is no narrower than int. If the source is compiled with _FILE_OFFSET_BITS == 64 this type is transparently replaced by off64_t.

y

off64_t This type is used similar to off_t. The difference is that even on 32 bit machines, where the off_t type would have 32 bits, off64_t has 64 bits and so is able to address files up to 2^63 bytes in length. When compiling with _FILE_OFFSET_BITS == 64 this type is available under the name off_t.

Por lo tanto, si desea una forma confiable de representar el tamaño del archivo entre el cliente y el servidor, puede:

  1. Utilice off64_t type y stat64() función en consecuencia (ya que llena la estructura stat64 , que contiene off64_t tipo sí mismo). Tipo off64_t garantiza el mismo tamaño en máquinas de 32 y 64 bits.
  2. Como se mencionó anteriormente, compile su código con -D_FILE_OFFSET_BITS == 64 y use off_t y stat() habituales.
  3. Convierta off_t para escribir int64_t con tamaño fijo (estándar C99). Nota: (mi libro ''C in a Nutshell'' dice que es C99 estándar, pero opcional en la implementación). El último estándar C11 dice:

    7.20.1.1 Exact-width integer types 1 The typedef name intN_t designates a signed integer type with width N , no padding bits, and a two’s complement representation. Thus, int8_t denotes such a signed integer type with a width of exactly 8 bits. without mentioning.

    Y sobre la implementación:

    7.20 Integer types <stdint.h> ... An implementation shall provide those types described as ‘‘required’’, but need not provide any of the others (described as ‘‘optional’’). ... The following types are required: int_least8_t uint_least8_t int_least16_t uint_least16_t int_least32_t uint_least32_t int_least64_t uint_least64_t All other types of this form are optional.

Por lo tanto, en general, C estándar no puede garantizar tipos con tamaños fijos. Pero la mayoría de los compiladores (incluido gcc) admiten esta función.


Dado que esta respuesta todavía se vota, quiero señalar que casi nunca debería tener que buscar en los archivos de encabezado. Si desea escribir un código confiable, lo mejor será que consulte el estándar. Una pregunta mejor que "cómo se define off_t en mi máquina" es "¿cómo está off_t definido por el estándar?". Seguir el estándar significa que su código funcionará hoy y mañana, en cualquier máquina.

En este caso, off_t no está definido por el estándar C. Es parte del estándar POSIX, que puedes buscar aquí .

Desafortunadamente, off_t no está definido muy rigurosamente. Todo lo que pude encontrar para definirlo está en la página en sys/types.h :

blkcnt_t y off_t serán tipos enteros con signo.

Esto significa que no puede estar seguro de cuán grande es. Si está usando GNU C, puede usar las instrucciones en la respuesta a continuación para asegurarse de que sean 64 bits. O mejor, puede convertir a un tamaño estándar definido antes de ponerlo en el cable. Así es como funcionan los proyectos como los Buffers de Protocolo de Google (aunque se trata de un proyecto de C ++).

Por lo tanto, creo que "¿dónde encuentro la definición en mis archivos de encabezado?" No es la mejor pregunta. Pero, para completar, aquí está la respuesta:

Encontrará la definición en bits/types.h (como dice un comentario en la parte superior, nunca incluya directamente este archivo), pero se oscurece un poco en un montón de macros. Una alternativa para tratar de desentrañarlos es observar el resultado del preprocesador:

#include <stdio.h> #include <sys/types.h> int main(void) { off_t blah; return 0; }

Y entonces:

$ gcc -E sizes.c | grep __off_t typedef long int __off_t; ....

Sin embargo, si quiere saber el tamaño de algo, siempre puede usar el operador sizeof() .

Editar: Acabo de ver la parte de tu pregunta sobre el __ . Esta respuesta tiene una buena discusión . El punto clave es que los nombres que comienzan con __ están reservados para la implementación (por lo que no debe comenzar sus propias definiciones con __ ).


Si está escribiendo código portátil, la respuesta es "no se puede saber", la buena noticia es que no es necesario. Su protocolo debe incluir escribir el tamaño como (por ejemplo) "8 octetos, formato big-endian" (Lo ideal sería verificar que el tamaño real cabe en 8 octetos).


Si tiene problemas para rastrear las definiciones, puede usar la salida preprocesada del compilador que le dirá todo lo que necesita saber. P.ej

$ cat test.c #include <stdio.h> $ cc -E test.c | grep off_t typedef long int __off_t; typedef __off64_t __loff_t; __off_t __pos; __off_t _old_offset; typedef __off_t off_t; extern int fseeko (FILE *__stream, __off_t __off, int __whence); extern __off_t ftello (FILE *__stream) ;

Si observa el resultado completo, incluso puede ver la ubicación exacta del archivo de encabezado y el número de línea donde se definió:

# 132 "/usr/include/bits/types.h" 2 3 4 typedef unsigned long int __dev_t; typedef unsigned int __uid_t; typedef unsigned int __gid_t; typedef unsigned long int __ino_t; typedef unsigned long int __ino64_t; typedef unsigned int __mode_t; typedef unsigned long int __nlink_t; typedef long int __off_t; typedef long int __off64_t;

...

# 91 "/usr/include/stdio.h" 3 4 typedef __off_t off_t;