| |
Páginas: [1] 2
|
 |
|
Autor
|
Tema: Necesito ayuda urgente sobre sockets! (Leído 773 veces)
|
alan_tgn
Desconectado
Mensajes: 13
|
Hola a todos, Bien, me acabo de registrar ya que stoy muy desesperado.... Aquí va el problema: Resulta que estoy haciendo el segundo curso de ASI (Administración de Sistemas Informáticos) i el profesor de DFSI (no m acuerdo de las siglas pero es para para saber programar en Linux i dentro de Linux pues saber programar en bash, C+... Nos ha pedido para final de curso, (osea ya..esta semana se acaba el plazo...aunque nos ha dicho que podría dejarnos una semana más), un trabajo que consiste en hacer un "blackjack" en C+ i poderlo ejeutar desde un menú en bash y luego poder jugar online i por red. El blackjack, ya hace que lo tengo hecho, tiene bastantes fallos pero bueno funciona...esque en C+ i en programación en general no esque sea mi fuerte. Ahora falta poder jugar online, es decir por SOCKETS. De sockets solo tengo que me funcione un mensaje que tengo escrito previamente al servidor , que le llega inmediatamente al cliente. Lo que pasa que no sé que tengo que hacer para poder enviar y recibir. Expliacado por aquí parece mucho lio, el mismo que tengo en mi cabeza... os deejo el código del servidor: #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #include <sys/wait.h> #define MYPORT 3490 /* the port users will be connecting to */ #define BACKLOG 100 /* how many pending connections queue will hold */ main() { int sockfd, new_fd; /* listen on sock_fd, new connection on new_fd */ struct sockaddr_in my_addr; /* my address information */ struct sockaddr_in their_addr; /* connector's address information */ int sin_size; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } my_addr.sin_family = AF_INET; /* host byte order */ my_addr.sin_port = htons(MYPORT); /* short, network byte order */ my_addr.sin_addr.s_addr = inet_addr ("127.0.0.1"); /* auto-fill with my IP */ memset(&(my_addr.sin_zero),'\0', 8); /* zero the rest of the struct */ if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1){ perror("Bind"); exit(1); } if (listen(sockfd, BACKLOG) == -1) { perror("listen"); exit(1); } while(1) { /* main accept() loop */ sin_size = sizeof(struct sockaddr_in); if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, \ &sin_size)) == -1) { perror("accept"); continue; } printf("server: got connection from %s\n", \ inet_ntoa(their_addr.sin_addr)); if (!fork()) { /* this is the child process */ if (send(new_fd, "Va el puñetero programaaaaa!\n", 100, 0) == -1) perror("send"); close(new_fd); exit(0); } close(new_fd); /* parent doesn't need this */ while(waitpid(-1,NULL,WNOHANG) > 0); /* clean up child processes */ } } y aquí el de el cliente: #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <netdb.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #define PORT 3490 /* the port client will be connecting to */ #define MAXDATASIZE 100 /* max number of bytes we can get at once */ int main(int argc, char *argv[]) { int sockfd, numbytes; char buf[MAXDATASIZE]; struct hostent *he; struct sockaddr_in their_addr; /* connector's address information */ if (argc != 2) { fprintf(stderr,"usage: client hostname\n"); exit(1); } if ((he=gethostbyname(argv[1])) == NULL) { /* get the host info */ error("gethostbyname"); exit(1); } if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } their_addr.sin_family = AF_INET; /* host byte order */ their_addr.sin_port = htons(PORT); /* short, network byte order */ their_addr.sin_addr = *((struct in_addr *)he->h_addr); bzero(&(their_addr.sin_zero), 8); /* zero the rest of the struct */ if (connect(sockfd, (struct sockaddr *)&their_addr, \ sizeof(struct sockaddr)) == -1) { perror("connect"); exit(1); } if ((numbytes=recv(sockfd, buf, MAXDATASIZE, 0)) == -1) { perror("recv"); exit(1); } buf[numbytes] = '\0'; printf("Received: %s",buf); close(sockfd); return 0; } Espero que alguien que sepa de SOCKETS me pueda hechar un cable...es super urgente ya que me juego el curso... Muchas gracias.
|
|
|
|
« Última modificación: 07 Mayo 2008, 11:20 por alan_tgn »
|
En línea
|
|
|
|
Flakito81
Desconectado
Mensajes: 350
|
Pues es lo mismo que tienes. en el cliente pones un bucle y en la parte de arriba lees del socket, si hay algo haces el tratamiento y si tienes q enviar envias como normal. codigo del cliente while (1) { recv(.......); //recibimos el mensaje del socket //tratamiento para la accion //enviar si es preciso
}
en el fork puedes tener una funcion para gestionar a los clientes y dentro de esa funcion lees del socket y escribes. Lo mismo sería interesante que crearas un array de sockets para que atiendiendas a varios clientes. y tambien el fd_set. fd_set grupo_de_sockets; FD_ZERO(&grupo_de_sockets);//inicializamos FD_SET(socket, &grupo_de_sockets); //agregamos el sockets al grupo if ((select(10, &grupo_de_sockets, NULL, NULL, NULL))<0) { perror("select"); exit(0); } /** si hay datos en el socket leemos, si no pasamos **/ if (FD_ISSET(socket ,&grupo_socks)) { memset(Buffer, '\x0', 512); recibir(socket,Buffer); } version extendida: fd_set grupo_de_sockets; FD_ZERO(&grupo_de_sockets);//inicializamos for (i = 0; i < NumeroClientes; ++i) FD_SET(socket_clientes[i], &grupo_de_sockets); if ((select(10, &grupo_de_sockets, NULL, NULL, NULL))<0) { perror("select"); exit(0); } /** Si tenemos datos de algun cliente (miramos en todos los sockets) **/ for (i = 0; i < NumeroClientes; ++i) if (FD_ISSET(socket_clientes[i] ,&grupo_socks)) { memset(Buffer, '\x0',512); recibir(socket_clientes[i], Buffer); //miramos si es algun comando //enviamos la informacion que sea al cliente i }//fin si //fin for Que conste que es únicamente un esquema general. Suerte!
|
|
|
|
|
En línea
|
|
|
|
alan_tgn
Desconectado
Mensajes: 13
|
Buenas, muchas gracias por responderme...
Ahora stoy provando pero no hay manera, muchas cosas me suenan a "chino"...
Intentaré provar mas suerte, pero por ahora me peta, y hay algunas cositas que no lo he cogido muy bien.
Si averiguo algo o tengo alguna duda ya volveré a escribir.
Gracias de nuevo
|
|
|
|
|
En línea
|
|
|
|
zhynar_X
Desconectado
Mensajes: 516
Use linux my friend...
|
Mira este manual sobre sockets, se entiende facilmente: http://www.starlinux.net/staticpages/index.php?page=20020720164837437 Saludos
|
|
|
|
|
En línea
|
Me he creado un blog: http://zhynar.blogspot.com Aver si os gusta!  Optimista es aquel que cree poder resolver un atasco de trafico tocando el claxon (Anonimo)
|
|
|
alan_tgn
Desconectado
Mensajes: 13
|
ese manual lo tengo agregado a mis favoritos...ya hace tiempo y nada...me resulta muy complicado.
Aver si saco algo en claro
Un saludo
|
|
|
|
|
En línea
|
|
|
|
alan_tgn
Desconectado
Mensajes: 13
|
Flakito88, veo que tu lo dominas...y veo que lo has pillao a la primera.
Te importaría aplicar ese codigo al mio??
Sé que es un poco de gorrón, pero he intendado hacer lo que tu has dicho pero no hay forma, no sé si lo hago yo mal o que...
Muchas gracias
|
|
|
|
|
En línea
|
|
|
|
zhynar_X
Desconectado
Mensajes: 516
Use linux my friend...
|
ese manual lo tengo agregado a mis favoritos...ya hace tiempo y nada...me resulta muy complicado.
Aver si saco algo en claro
Un saludo
Si no te enteras te aconsejo que leas sobre estructuras de datos y punteros, que es lo mas "conmplicado" de los sockets. Saludos 
|
|
|
|
|
En línea
|
Me he creado un blog: http://zhynar.blogspot.com Aver si os gusta!  Optimista es aquel que cree poder resolver un atasco de trafico tocando el claxon (Anonimo)
|
|
|
skapunky
Electronik
Colaborador
Desconectado
Mensajes: 1.228
www.killtrojan.es
|
|
|
|
|
|
En línea
|
|
|
|
alan_tgn
Desconectado
Mensajes: 13
|
justamente tengo suspendida programación de priemero que entraba C+ i VB...
En temas de punteros y estructuras ando un poco mal, por no decir mucho...l
DFSI la he ido sacando como he podido y a demás los dos trimestres con sietes...pero aquí se complica la cosa....yo y la mayoría de la clase también lo llevan jodido...
He podido hacer que el servidor envie una frase al cliente...pero ahora viene cuando la matan...que falta que envie y reciba el blackjack...y esque no tengo ni pajolera idea.
Me he leido paso por paso varios manuales...pero es complicado sacar algo en claro, por que ahí solo hay ejemplos para hacer ver como funciona un sockets sencillo con un "hola mundo"...
no sé... ahora me pondreé otra vez más por variar...llevo con el programa ya tres
Un saludo
|
|
|
|
|
En línea
|
|
|
|
E0N
Lab &
Colaborador
Conectado
Mensajes: 2.682
|
|
|
|
|
|
En línea
|
|
|
|
alan_tgn
Desconectado
Mensajes: 13
|
el priemer enlace que me has pasado EON, lo tengo agregado en favoritos.... es muy buena pagina, aunque a veces el narrador se monta unas historias que hay veces que te descoloca un poco. Pero tiene muchsisimos ejemplos. Ahora el problema que tengo es con lo de enviar y recibir bytes constantes. El FLAKITO81 lo ha pillado y me ha puesto lo que debería hacer. Lo que no entiendo muy bien el while del clietne dónde va y como. También tengo algunas dudas con el fork()...pensareis que tengo dudas en todo...en cierto modo algo, la verdad, para que engañarnos. Haber si me podéis ayudar mezclando el ejemplo con mi código. Si hace falto pago  Muhas gracias a todos lo que se lo estan currando... Saludos!
|
|
|
|
|
En línea
|
|
|
|
Flakito81
Desconectado
Mensajes: 350
|
No dispongo de tiempo pero gastaré 5 minutos en este post. El cliente no tiene nada de ciencia, lo logico es que el cliente envie algo al servidor y el servidor responda y mientras no se reciba respuesta el cliente se quede esperando. Por ello te dije que el bucle while deberia de seguir esta estructura. while(1) { //leemos del socket (recv, read, ....)
// en base a lo q el servidor nos envia respondemos }
El servidor puede llevar mayor trabajo, si lo que quieres es atender a varios clientes. Te pongo el codigo de un servidor para ello (la comprobacion de errores te lo dejo para ti): #define CONEXIONES 5 int numero_de_hijos = 0; void proceso_hijo( int socket_servidor) { fd_set grupo, grupo_todos; int maxfd = socket_servidor; int ceiling = 0; int i; FD_ZERO(&grupo); FD_ZERO(&grupo_todos); FD_SET(socket_servidor, &grupo_todos); while(1) { grupo = grupo_todos; if ( select(maxfd+1, &grupo, 0, 0, 0) > 0 ) { for ( i = 0; i < maxfd + 1; ++i) { if ( FD_ISSET(i, &grupo) ) { if ( i == socket_servidor ) { if ( ceiling < CONEXIONES ) { int client = accept(socket_servidor, 0, 0); if ( maxfd < client ) maxfd = client; FD_SET(client, &grupo_todos);//lo añadimos al grupo ceiling++; printf("select proceso #%d: %d conexiones\n", getpid(), ceiling); }//fin si } else { char buffer[1024]; int bytes; memset (buffer, '\x0', sizeof(buffer)); bytes = recv(i, buffer, sizeof(buffer), 0); printf ("El cliente %d nos envia: %s\n", i - 3, buffer); if ( bytes == 0 ) { close(i); FD_CLR(i, &grupo_todos);//lo quitamos del grupo ceiling--; printf("select process #%d: %d conexiones\n", getpid(), ceiling); } else /* enviamos al cliente lo mismo que recibimos (servidor de eco)*/ send(i, buffer, bytes, 0); }//fin else }//fin si(FD_ISSET) } //fin for }//fin si (select) }//fin while(1) exit(0); }// fin 'proceso_hijo' int main() { int sock, pid; struct sockaddr_in local; struct hostent *dir_server; socklen_t len; if((dir_server=gethostbyname("127.0.0.1"))==0) { printf("Error al resolver la direccion del server"); exit(1); } sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); local.sin_family=AF_INET; local.sin_addr=*((struct in_addr*)dir_server->h_addr); local.sin_port=htons(8888); memset(&(local.sin_zero),'\0',8); printf ("Servidor iniciado\n"); if (bind(sock, (struct sockaddr *) &local, sizeof(local)) == 0) { listen(sock, CONEXIONES); while (1) { if (numero_de_hijos < CONEXIONES) { if ((pid = fork()) == 0) proceso_hijo(sock); else if (pid > 0) numero_de_hijos++; else perror("fork"); }//fin si else sleep(1); }//fin while(1) }//fin si (bind) else perror("bind"); return 0; }//fin main Si mas tarde tengo algo de tiempo te pongo como sería el cliente. Aun asi te pongo el bucle principal de un bot de irc que hice hace años para que veas la estructura. do{ receive(buffer); //leemos del socket p=parseo(buffer); //funcion rudimentaria para parsear (un strtok casero) if(!strcmp(p->parv[0],"PING")) //si el servidor nos envia un ping pong(p->parv[1]); //le respondemos con un pong else if(!strcmp(p->parv[1],"PRIVMSG")){ //si es un mensaje privado u=remitente(p->parv[0]); //leemos de quien viene if(strncmp("#",p->parv[2],1)){ //si no se envia a un canal chrrm58(p->parv[3]); //borramos algunos caracteres /* miramos si hay que ignorarlo (ChanServ, NickServ) * de no hacerse asi se crearia un bucle infinito y caeriamos *por flood */ for(i=0;i<2;i++) if(!strcasecmp(ignorar[i],u->nick)) continue; /* Miramos si está autorizado */ if(!is_gestor(u->nick)) { privmsg(u->nick,ACCDENIED); continue; } /* miramos si nos ha enviado un comando */ for(i=0;cmd[i].comando;++i) //miramos la lista de comandos if(!strcasecmp(p->parv[3],cmd[i].comando))//si es comando activo=cmd[i].pf(u); //ejecutamos accion asociada } } libera_memoria(p); //por lo del parseo rudimentario (no conocia strtok :-)) }while(activo); Suerte! PD: me acabo de dar cuenta que al pasar del editor al foro se jodieron los tabulados, ya te encargas tu de solucionarlo
|
|
|
|
« Última modificación: 06 Mayo 2008, 20:16 por Flakito81 »
|
En línea
|
|
|
|
alan_tgn
Desconectado
Mensajes: 13
|
Buenos días... Bien he cogido el código de Flakito81 y lo he "mezclado" con el mio, priori cuando lo compilo pensando que habrían muchos errores, pues ninguno. Ahora bien cuando ejecuto me sale el error: bind: Socket operation on non-socket. No sé si he hecho bien a la hora de mezclar, me he copiado lo de los padres e hijos para poder enviar i recibir sin problemas. Os dejo el código del server por si sábeis por qué me ocurre esto: #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #include <sys/wait.h> #define MYPORT 3490 /* the port users will be connecting to */ #define BACKLOG 100 #define CONEXIONES 5 int numero_de_hijos = 0; void proceso_hijo( int socket_servidor) { fd_set grupo, grupo_todos; int maxfd = socket_servidor; int ceiling = 0; int i; FD_ZERO(&grupo); FD_ZERO(&grupo_todos); FD_SET(socket_servidor, &grupo_todos); while(1) { grupo = grupo_todos; if ( select(maxfd+1, &grupo, 0, 0, 0) > 0 ) { for ( i = 0; i < maxfd + 1; ++i) { if ( FD_ISSET(i, &grupo) ) { if ( i == socket_servidor ) { if ( ceiling < CONEXIONES ) { int client = accept(socket_servidor, 0, 0); if ( maxfd < client ) maxfd = client; FD_SET(client, &grupo_todos);//lo añadimos al grupo ceiling++; printf("select proceso #%d: %d conexiones\n", getpid(), ceiling); }//fin si } else { char buffer[1024]; int bytes; memset (buffer, '\x0', sizeof(buffer)); bytes = recv(i, buffer, sizeof(buffer), 0); printf ("El cliente %d nos envia: %s\n", i - 3, buffer); if ( bytes == 0 ) { close(i); FD_CLR(i, &grupo_todos);//lo quitamos del grupo ceiling--; printf("select process #%d: %d conexiones\n", getpid(), ceiling); } else /* enviamos al cliente lo mismo que recibimos (servidor de eco)*/ send(i, buffer, bytes, 0); }//fin else }//fin si(FD_ISSET) } //fin for }//fin si (select) }//fin while(1) exit(0); }// fin 'proceso_hijo' main() { int sock, pid; struct sockaddr_in local; struct hostent *dir_server; socklen_t len; int sockfd, new_fd; /* listen on sock_fd, new connection on new_fd */ struct sockaddr_in my_addr; /* my address information */ struct sockaddr_in their_addr; /* connector's address information */ int sin_size; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } my_addr.sin_family = AF_INET; /* host byte order */ my_addr.sin_port = htons(MYPORT); /* short, network byte order */ my_addr.sin_addr.s_addr = inet_addr ("127.0.0.1"); /* auto-fill with my IP */ memset(&(my_addr.sin_zero),'\0', 8); /* zero the rest of the struct */ if (bind(sock, (struct sockaddr *) &local, sizeof(local)) == 0) { listen(sock, CONEXIONES); while (1) { if (numero_de_hijos < CONEXIONES) { if ((pid = fork()) == 0) proceso_hijo(sock); else if (pid > 0) numero_de_hijos++; else perror("fork"); }//fin si else sleep(1); }//fin while(1) }//fin si (bind) else perror("bind"); return 0; }//fin main Muchas gracias a todos aquellos que muestran interés por esto. Saludos!
|
|
|
|
|
En línea
|
|
|
|
Flakito81
Desconectado
Mensajes: 350
|
Al bind le estas pasando socket y le tendrias que pasar sockfd que es el descriptor. Hay q fijarse mas!
Saludos!
|
|
|
|
|
En línea
|
|
|
|
|
| | |