Discussion:
cadena de 32 bits a long???
(demasiado antiguo para responder)
I3iT
2006-01-11 19:44:54 UTC
Permalink
Hola, a ver si alguien puede ayudarme.

Estoy realizando un cliente para el protocolo TIME (rfc868;
ftp.ietf.org/rfc/rfc0868.txt).

La cuestion es que tengo todo hecho pero el problema es q el servidor manda
los segundos como un numero de 32 bits. Bien, yo recibo los 4 bytes en un
array: buffer[]

La cuestion es como hacer un solo numero con los 4 bytes q tengo
partidillos en el array. Yo lo intente asi pero las fecha q obtengo no es
buena....

segundos= ((time_t)buffer[0]*16777216);
segundos=segundos+((time_t)buffer[1]*65536);
segundos=segundos+((time_t)buffer[2]*256);
segundos=segundos+((time_t)buffer[3]);

Seguro q es una bobada pero no logro hacerlo.
Salu2<
Oscar Garcia
2006-01-11 22:56:54 UTC
Permalink
Post by I3iT
Hola, a ver si alguien puede ayudarme.
Estoy realizando un cliente para el protocolo TIME (rfc868;
ftp.ietf.org/rfc/rfc0868.txt).
La cuestion es que tengo todo hecho pero el problema es q el servidor manda
los segundos como un numero de 32 bits. Bien, yo recibo los 4 bytes en un
array: buffer[]
Lo mejor sería leerlo directamente sobre un unsigned int (o un
uint32_t) y no sobre un char buffer[] (supongo que te referías a tipos
de datos char).
Post by I3iT
La cuestion es como hacer un solo numero con los 4 bytes q tengo
partidillos en el array. Yo lo intente asi pero las fecha q obtengo no es
buena....
segundos= ((time_t)buffer[0]*16777216);
segundos=segundos+((time_t)buffer[1]*65536);
segundos=segundos+((time_t)buffer[2]*256);
segundos=segundos+((time_t)buffer[3]);
Si todos los valores son unsigned entonces debería funcionarte bien.
Yo usaría (más rápido) lo siguiente:

segundos = (uint)buffer[0] << 24;
segundos = (uint)buffer[1] << 16;
segundos = (uint)buffer[2] << 8;
segundos = (uint)buffer[3];

¿Seguro que el orden es el correcto?
Post by I3iT
Seguro q es una bobada pero no logro hacerlo.
Lo mejor siempre es usar un "union" para estas cosas:

union {
char buffer[4];
uint32_t hora;
} ambos;

Recuerda usar los network to host de C (ntohl) para convertir formato
de datos de red a formato de datos de la máquina.

¿Es el formato de tiempo el mismo que es usado por las funciones de
hora de C?

No me he parado a documentarme ni responderme estas cuestiones, pero
son cosas que debes plantearte.

Un saludo.
--
Óscar Javier García Baudet
LinaresDigital
http://redstar.linaresdigital.com/
Antoine Leca
2006-01-13 15:47:38 UTC
Permalink
Post by I3iT
La cuestion es que tengo todo hecho pero el problema es q el servidor
manda los segundos como un numero de 32 bits. Bien, yo recibo los 4
bytes en un array: buffer[]
¿Como está declarado?
Post by I3iT
Yo lo intente asi pero las fecha q obtengo no es buena....
Precisa: que querres, que recibes.

Parece que el cáculo es correcto. Pero no sabemos si las datos lo son
(concretamente el orden). Un error común es de enviar (o recibir) los datos
como un uint32_t, que usa el orden del ordenador. Y un PC usa el orden
(/endianness/) inverso del orden oficial de la red... Entonces va bién entre
dos PCs que hacen el mismo error; pero no interopera, y tampoco corre si
respectes el protócolo en uno solo de los lados.


Antoine
Pedro Maicas
2006-01-13 18:01:39 UTC
Permalink
Post by I3iT
los segundos como un numero de 32 bits. Bien, yo recibo los 4 bytes en un
array: buffer[]
todo depende del orden en el que esten los bytes, si va primero la
parte menos signigicativa o la mas significativa, la conversion
podría ser tan sencilla como:

unsigned long segundos; //32 bits, supongo
segundos = *(long*)buffer;

si esto no sirve (porque el numero va al revés) entonces
inviente el orden de los bytes, es decir añade a lo anterior:

segundos =
((segundos >> 24) & 0x000000FF) |
((segundos >> 8) & 0x0000FF00) |
((segundos << 8) & 0x00FF0000) |
((segundos << 24) & 0xFF000000);


Lo que has hecho tu tambien está bien, si el rfc dice que
que buffer[0] es el byte más significativo, que no lo voy a
mirar, pero te fallará seguramente por usar signed char, que
expandirá el signo de los bytes mayores a 127, prueba así:

segundos =
(time_t)(unsigned char)buffer[0]*16777216 +
(time_t)(unsigned char)buffer[1]*65536 +
(time_t)(unsigned char)buffer[2]*256 +
(time_t)(unsigned char)buffer[3];

O así que es igual pero mola más:

segundos =
((time_t)(unsigned char)buffer[0] << 24) |
((time_t)(unsigned char)buffer[1] << 16) |
((time_t)(unsigned char)buffer[2] << 8) |
((time_t)(unsigned char)buffer[3];


Saludos :-) -Pedro-

http://www.maicas.net/

e-mail en www.maicas.net
I3iT
2006-01-15 13:37:47 UTC
Permalink
Muchas gracias a los 3 por las ideas, esta tarde/noche lo pruebo y os
comento los resultados. A ver si lo consigo xq me tiene comida la moral la
chorradita esta.
Salu2<
I3iT
2006-01-16 13:42:01 UTC
Permalink
Vaya vaya... resulta que la conversion del numero de 32 bits que recibo
del server esta bien, obtengo lo mismo empleando todas las opciones.

Lo que me parece que no tengo bien es al pasarlo a la funcion ctime, que
devuelve un formato 'bonito' para dicha fecha. Expongo:


char buffer[10]; // buffer de datos recibidos del
servidor
int long *p_segundos, segundos; // 32 bits (time_t o int long)

n=read(sd, (void*)buffer, 10); // Recibe 4 bytes
buffer[n]='\0';
fprintf(stdout,"\n Bytes leidos desde el servidor: %d ---> %
s",n,buffer);

p_segundos=(unsigned int long*)buffer;
segundos=ntohl(*p_segundos);
printf("\n Time recibido del server como 32 bits: %u\n",segundos);

//Bien, aqui obtengo el valor: 3346406318

printf("\n %s", ctime((time_t*)&segundos));

// Obteniendo: Mon Dec 11 07:50:22 1939 que esta mal.....



Buscando encontre esto:

// el numero de abajo corresponde a 00:00 1 May 1983 GMT,
segundos2=(unsigned int long )2629584000;
printf("\n %s", ctime((time_t*)&segundos2));

Con esto modifico mi programa haciendo:

segundos=(unsigned int long )2629584000;
printf("\n %s", ctime((time_t*)&segundos));

A lo que al compilar tengo el warnning:

practica_1.c:118: warning: decimal constant is so large that it is
unsigned

Y obtengo la bonita fecha de: Sat Mar 24 18:31:44 1917


He probado con:

segundos=(unsigned int long )629584000;
printf("\n %s", ctime((time_t*)&segundos));

A lo cual al compilar no obtengo warnning alguno y al ejecutarlo la
fecha que obtengo es: Wed Dec 13 21:26:40 1989


Perdon por el tocho. Agradezco vuestra ayuda, que esto ya me supera.

Salu2

Loading...