[Solucionado] Programando socke cliente y servidor en C

Iniciado por r1ghtz0, 14 Octubre 2014, 22:17 PM

0 Miembros y 1 Visitante están viendo este tema.

r1ghtz0

Aquí está el servidor, lo que hago es ingresar los datos del servidor pero me gustaría ver cual es la ip que se le asigna al servidor con INADDR_ANY, ¿Como puedo hacer para ver la ip del server?

Servidor:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main(void)
{
/* Abriendo socket */
int sockfd, new_sockfd;
struct sockaddr_in server_addr;
struct sockaddr_in cliente_addr;
int addrlen;

sockfd= socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1){
printf("Error abriendo el socket...");
}

/* Asociación de parámetros al socket */
server_addr.sin_family= AF_INET;
server_addr.sin_port= htons(1234);
server_addr.sin_addr.s_addr= htonl(INADDR_ANY);

if(bind(sockfd, (struct sockaddr *) &server_addr, sizeof(server_addr))==-1){
printf("\nError en bind()...");
}

/* Habilitamos el socket para recibir peticiones y establecer conexiones */
listen(sockfd, 5);
addrlen= sizeof(struct sockaddr);

/* Recibimos peticiones con accept() */
new_sockfd= accept(sockfd, (struct sockaddr *) &cliente_addr, &addrlen);
if(new_sockfd == -1){
printf("Error, no se pudo recibir petición correctamente");
}

return 0;
}



Cliente:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main(void)
{
struct sockaddr_in server;
char ip[16];
int fd, puerto;
int addrlen;

printf("Ingrese la ip del servidor\n");
scanf("%s", ip);

printf("Ingrese el puerto de conexión\n");
scanf("%d", &puerto);

/* Abrimos el socket */
fd= socket(AF_INET, SOCK_STREAM, 0);
if(fd==-1){
printf("Error abriendo el socket");
return -1;
}

/* Definimos los datos del servidor */
server.sin_family= AF_INET;
server.sin_port= htons(1234);
server.sin_addr.s_addr= inet_addr(ip);

addrlen= sizeof(struct sockaddr);

if(connect(fd, (struct sockaddr *)&server, addrlen) == -1){
printf("\nHa ocurrido un error al conectarce al server");
}


return 0;
}


Ok, ahora el código del cliente pide que ingreses la IP del servidor, cómo puedo saber la ip del servidor si coloque INADDR_ANY en el campo s_addr del servidor, y eso lo que hace es dejar que el SO le asigne una ip al servidor. También veo que el cliente declara un "char ip[16]" de 16 bytes para almacenar la ip del server cuando en realidad la ip ocupa 4 bytes (32 bits). Para rematar, tenemos la siguiente linea de código:


server.sin_addr.s_addr= inet_addr(ip);


Viendo que la funcion inet_addr() es de esta manera:

in_addr_t inet_addr(const char *cp);

Como el array ip se pasa a la función inet_addr() el puntero cp va apuntar al primer elemento de ip y también podrá apuntar a cada uno de los elementos de ip, así que la función inet_addr se la apañará para retornar la dirección ip, eso es lo que entiendo.



ivancea96

#1
El array ip es de 16 y no de 4 porque ya me dirás cómo metes 4 bytes por pantalla xD
Inet_addr convierte el formato "#.#.#.#" a 4 bytes.
La IP que le pasas al cliente es la ip por la que te conectas a su máquina. Por ejemplo, si está en tu propia máquina, pondrías localhost (127.0.0.1).

r1ghtz0

#2
Cita de: ivancea96 en 14 Octubre 2014, 23:37 PM
El array ip es de 16 y no de 4 porque ya me dirás cómo metes 4 bytes por pantalla xD
Inet_addr convierte el formato "#.#.#.#" a 4 bytes.
La IP que le pasas al cliente es la ip por la que te conectas a su máquina. Por ejemplo, si está en tu propia máquina, pondrías localhost (127.0.0.1).
Espera un minuto, que quieres decir con "ya me dirás cómo metes 4 bytes por pantalla xD", a ver que no entiendo. Yo puedo ingresar 4 bytes por pantalla de esta forma:

Código ( c) [Seleccionar]

#include <stdio.h>

int main(void){
char vec[4];

scanf("%s", vec);

return 0;
}

ivancea96

#3
Tú puedes ingresar letras y caracteres imprimibles, pero no caracteres no imprimibles. Cada byte va de 0 a 255.

r1ghtz0

Cita de: ivancea96 en 15 Octubre 2014, 08:01 AM
Tú puedes ingresar letras y caracteres imprimibles, pero no caracteres no imprimibles. Cada byte va de 0 a 255.

No te entendí a la final, si no se pueden ingresar 4 bytes por pantalla entonces como es que si ingresas 16 bytes por pantalla. Otra cosa es que, no sé si alguien pueda ayudarme a pasarle la dirección IP del servidor al cliente, la IP del cliente yo se que es 127.0.0.1, es decir la de mi PC pero la IP del servidor no se cual es ni se como verla. Yo lo que quiero es conectar estos dos sockets en un mismo PC bajo Linux Mint pero el otro problema que tengo es ese, que no se cual IP se le asigna al servidor.

ivancea96

El servidor lo pones a escuchar a un puerto.
El cliente, lo conectas a ese mismo puerto, en la IP en la que esté el servidor (127.0.0.1, 192.168.1.X, u otra IP pública)

Un char es un dato de 8 bits, es decir, en sistema decimal, del 0 al 255, ambos incluídos. Cuando escribes una letra, es un número, ya sea en ASCII, UTF, o el sistema que sea. Los 4 chars que te pide la función son 4 bytes, cada uno de 0 a 255. Con letras, tú no puedes poner todos los valores en un solo caracter.

r1ghtz0

Cita de: ivancea96 en 15 Octubre 2014, 21:02 PM
El servidor lo pones a escuchar a un puerto.
El cliente, lo conectas a ese mismo puerto, en la IP en la que esté el servidor (127.0.0.1, 192.168.1.X, u otra IP pública)

Un char es un dato de 8 bits, es decir, en sistema decimal, del 0 al 255, ambos incluídos. Cuando escribes una letra, es un número, ya sea en ASCII, UTF, o el sistema que sea. Los 4 chars que te pide la función son 4 bytes, cada uno de 0 a 255. Con letras, tú no puedes poner todos los valores en un solo caracter.

ivancea96 lo que me estás diciendo del char ya lo se, yo lo que quiero saber es cual es la IP que el sistema operativo le asigna al server ¿Como puedo obtener esa IP del server? Y por qué el cliente almacena la IP del server en un array de 16 elemento? específicamente por qué el array es de 16 elementos? es todo.

cpu2

#7
Cita de: r1ghtz0 en 16 Octubre 2014, 01:39 AM
ivancea96 lo que me estás diciendo del char ya lo se, yo lo que quiero saber es cual es la IP que el sistema operativo le asigna al server ¿Como puedo obtener esa IP del server? Y por qué el cliente almacena la IP del server en un array de 16 elemento? específicamente por qué el array es de 16 elementos? es todo.

Buscando un poco en los manuales de Linux encontraras las funciones que necesitas, no sera por falta de documentacion, algunas de las que te digo son estas, igualmente no se que necesitas al 100%.

getsockname, getaddrinfo, gethostbyaddr etc...

Estan todas muy bien documentadas, lee los manuales que estan perfectamente comentados y sabras cual es la que te conviene.


Sobre el tema del vector, cuando llamas a scanf y pasa las direccion esta esta en formato ASCII, igualemnte no ves que se solicita una cadena en scanf.

El simple motivo de porque tiene 16 bytes el vector ip es este. Si sabiendo que una direccion IPv4 puede estar en el rango 255.255.255.255 y que los numeros o simbolos que introduces para crear esa direccion son un byte se queda en 15 bytes el sobrante sera por la basura que deja scanf, o el byte nulo.

Pero tu necesitas un entero de 4 bytes en el rango 0 - 255, no 15 bytes en formato ASCII, lo que hace inet_addr es pasar la direccion en formato string a un int de 4 byes. Seria esto 127.0.0.1 (string) == 0x100007f, ese numero en HEX estaria  bien, se entiende?

Si quieres ser mas PRO, utiliza argv (linea de comando) y dejate de funciones como esa, para tomar valores por parte del usuario, argv el ultimo byte seria un 0, supongo que sabras que siginifica el 0 cuando estas trabajando con cadenas.

Y otra cosa, en el code CLIENTE solicitas el puerto, pero estas usando una previeamente establecido.

Un saludo.

r1ghtz0

Cita de: cpu2 en 16 Octubre 2014, 07:43 AM
Buscando un poco en los manuales de Linux encontraras las funciones que necesitas, no sera por falta de documentacion, algunas de las que te digo son estas, igualmente no se que necesitas al 100%.

getsockname, getaddrinfo, gethostbyaddr etc...

Estan todas muy bien documentadas, lee los manuales que estan perfectamente comentados y sabras cual es la que te conviene.


Sobre el tema del vector, cuando llamas a scanf y pasa las direccion esta esta en formato ASCII, igualemnte no ves que se solicita una cadena en scanf.

El simple motivo de porque tiene 16 bytes el vector ip es este. Si sabiendo que una direccion IPv4 puede estar en el rango 255.255.255.255 y que los numeros o simbolos que introduces para crear esa direccion son un byte se queda en 15 bytes el sobrante sera por la basura que deja scanf, o el byte nulo.

Pero tu necesitas un entero de 4 bytes en el rango 0 - 255, no 15 bytes en formato ASCII, lo que hace inet_addr es pasar la direccion en formato string a un int de 4 byes. Seria esto 127.0.0.1 (string) == 0x100007f, ese numero en HEX estaria  bien, se entiende?

Si quieres ser mas PRO, utiliza argv (linea de comando) y dejate de funciones como esa, para tomar valores por parte del usuario, argv el ultimo byte seria un 0, supongo que sabras que siginifica el 0 cuando estas trabajando con cadenas.

Y otra cosa, en el code CLIENTE solicitas el puerto, pero estas usando una previeamente establecido.

Un saludo.
cpu2 muchas gracias por aclararme lo del vector ahora si lo entiendo, el vector tiene 16 elementos porque la dirección IP puede tener hasta 15 caracteres. Y lo de la dirección IP del servidor y el cliente, también lo pude entender gracias a una ayuda que me dieron en otro foro, si el servidor y el cliente están en la misma PC entonces tomaran la misma dirección, es decir, 127.0.0.1. Si están en ordenadores de distintas partes del mundo entonces servidor y cliente tomarán la IP pública del ordenador  donde estén. Y si están en la misma red local entonces tomaran la IP de cada host de la red.