[C con Clase] problema con sockets
Programante
programante en gmail.com
Jue Ene 31 12:54:41 CET 2008
nree escribió:
> Hola gente!!!
>
> trabajo con eclipse en un ubuntu y estoy haciendo un programilla con sockets. Para empezar lo de siempre, un servidor concurrente y un cliente que pide peticiones. Mi problema viene al crear los procesos hijos, se supone que envian al cliente un saludo y listo, pero... me tira el perror al hacer el send y despues de un rato lo hace. Es decir, me explico, el servidor se queda un rato con "bad file descriptor" y despues aparece en el cliente el mensaje. Y ademas la concurrencia no funciona.
>
> Os dejo los codigos...
>
> servidor.cpp
>
> int main(void) {
>
> int sock;
> int sock_dialog;
> struct sockaddr_in dir_ser;
> struct sockaddr_in dir_cli;
> int numbytes;// numbytes2;
> int yes=1;// conectado=0;
> socklen_t len;
> char buf[TAMBUF];
> //char buf2[TAMBUF];
>
>
> sock = socket(PF_INET, SOCK_STREAM,0);
> if (sock < 0)
> {
> perror("error de creación de socket");
> //exit(1);
>
Yo compararía con -1. En Linux da igual pero en otros sistemas podría
haber valores negativos distintos de -1 que sean válidos.
Como tienes comentados todos los exit(), en caso de fallo se ejecutará
una ruta de código no deseada (probablemente fallando todo).
> }
> else
> {
> puts("socket creado...");
> }
>
> dir_ser.sin_family = PF_INET;
> dir_ser.sin_addr.s_addr = htonl (INADDR_ANY);
>
INADDR_ANY no hace falta pasarlo a través de htonl(), pero no pasa nada.
> dir_ser.sin_port = htons (PORT);
> memset(dir_ser.sin_zero, '\0', sizeof dir_ser.sin_zero);
>
> if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1)
> {
> perror("setsockopt");
> //exit(1);
> }
>
> if (bind(sock, (struct sockaddr *)&dir_ser,sizeof dir_ser)< 0)
> {
> perror("error en la asignación de dirección");
> //exit(1);
> }
> else
> {
> puts("asignando direccion...");
> }
>
> if (listen (sock, NUM_CON) < 0)
> {
> perror("error en la escucha");
> //exit(1);
> }else
> puts("socket a la escucha...");
>
> while(1)
> {
> len = sizeof dir_ser;
> sock_dialog = accept(sock, (struct sockaddr *) &dir_cli, &len);
> if (!fork())
> {
> shutdown(sock,2);
> strcpy(buf, "respuesta desde servidor...");
> numbytes = send (sock_dialog, buf, sizeof(buf), 0);
>
En vez de sizeof(buf), creo que quieres hacer strlen(buf) o
strlen(buf)+1 dependiendo de si quieres enviar el caracter nulo o no.
> if (numbytes < 0)
> {
> perror("error en la transmision de datos...");
> }
> //tramitarChat((struct sockaddr_in *)sock_dialog);
>
aquí deberías finalizar el proceso hijo, para que no se quede atrapado
en el bucle diseñado para el padre.
sock_dialog es un socket, de tipo int, no hagas un casting a (struct
sockaddr_in *), usa dir_cli
> }
> shutdown(sock_dialog,2);
> }
> }
>
> cliente.cpp
>
> int main (int argc, char *argv[])
> {
> int sock, i;
> struct sockaddr_in dir_serv;
> char buf[TAMBUF];
>
> sock = socket (PF_INET, SOCK_STREAM, 0);
> if (sock < 0)
> {
> perror("No se ha podido crear el socket");
> exit (-1);
> }else
> puts ("socket creado...");
>
> dir_serv.sin_family = PF_INET;
> dir_serv.sin_port = htons (PORT);
> inet_aton(argv[1], &(dir_serv.sin_addr));
> memset(dir_serv.sin_zero, '\0', sizeof dir_serv.sin_zero);
>
> if (connect (sock, (struct sockaddr*)&dir_serv, sizeof dir_serv) <0)
> {
> perror("conexión no aceptada");
> exit(-1);
> }else
> puts("conectando con el servidor...");
>
> i = recv (sock, buf, sizeof(buf),0);
>
Esto se bloqueará hasta que se llene el buf. Dado que estamos a un nivel
básico, puedes probar
while ((recv (sock, buf, 1,0) > 0) && buf[0]) putchar(buf[0]);
> puts(buf);
>
Si decides no enviar el caracter nulo, no pudes usar puts(). Siempre es
recomendable utilizar el valor de bytes recibidos. write(1, buf, i);
> shutdown(sock,2);
> }
>
>
Todos los usos de shutdown() deberían ser close()
> gracias por vuestra colaboracion
>
De nada :)
> nere
Más información sobre la lista de distribución Cconclase