2010-11-15 13 views
5

Estoy escribiendo a clone of inetd en el que debo ejecutar un servidor que imprime la IP y el puerto del cliente que se conecta a él.Recuperación de IP/Puerto del Descriptor de Socket

Mientras sobreescribo STDIN y STDOUT con el descriptor de socket, my initial solution de hacer esto era recuperar la estructura sockaddr_in, que contiene la información necesaria. Sin embargo, al hacer esto con getsockname(), se devuelve una estructura vacía, con todos los bits configurados en 0.

¿Alguna idea de lo que está mal con mi enfoque? ¿Hay algún otro enfoque que pueda usar para recuperar el IP/Puerto?

Gracias

Respuesta

8

Como R .. señaló, debe usar getpeername. Tanto esa función como getsockname toman un descriptor de archivo como su primer argumento, no un puntero de flujo (FILE *). Use fileno(stdin) para obtener el descriptor de archivo para la entrada estándar (o codifíquelo en STDIN_FILENO, ya que es constante).

Además, el último argumento de getsockname y getpeername debe ser un puntero a socklen_t, no es una constante, y se debe utilizar un sockaddr_in para TCP/IP:

struct sockaddr_in peeraddr; 
socklen_t peeraddrlen = sizeof(peeraddr); 
getpeername(STDIN_FILENO, &peeraddr, &peeraddrlen); 

Véase un ejemplo completo here.

+0

OP mencionó "sobrescribir" stdin y stdout con el descriptor de archivo para el socket, que está mal redactado en el mejor de los casos, pero podría indicar que el reemplazo se está haciendo incorrectamente y stdin (fd 0) no es realmente un socket ... –

+0

@R .., revisa su código en https://github.com/konr/Licio/blob/master/05/time.c –

+1

No sé si este es * el * problema, pero usar 'struct sockaddr' excepto como un sustituto realmente feo para' void * 'siempre es un error. Nunca debería tener objetos reales de tipo 'struct sockaddr'. Siempre use 'struct sockaddr_in',' struct sockaddr_in6', o 'struct sockadd_storage', según sea necesario. –

3

Use getpeername. Sospecho que su problema es que getsockname devuelve la información para su propio lado (local) del socket, que probablemente está vinculado a 0.0.0.0 (lo que significa que puede aceptar conexiones desde cualquier interfaz).

Editar: Creo que encontré su error actual leyendo el código. Esta línea está mal:

getsockname(stdin, &addr, sizeof(addr)); 

Los getsockname y getpeername funciones toman un socklen_t * (un puntero ) como su tercer argumento, no una size_t. El compilador debería decirle sobre este error a menos que haya olvidado incluir un encabezado con el prototipo para getsockname. Además, como ya se ha dicho, stdin es incorrecto. Proveedores:

socklen_t len = sizeof addr; 
getpeername(0, &addr, &len); 

o (C99 solamente):

getpeername(0, &addr, (socklen_t[1]){sizeof addr}); 

También debe comprobar el valor de retorno; si lo hicieras, verías que están devolviendo errores.

+0

sin uso, el resultado es todavía 0. – konr

+2

Si quiere decir que getpeername() devuelve 0, significa que la función ha sido exitosa. – Simone

Cuestiones relacionadas