La recuperación de IP / Puerto de descriptor de socket
Pregunta
Estoy escribiendo un clon de inetd en el cual debo ejecutar un servidor que imprime el IP y el puerto del cliente que se conecta a ella.
Mientras STDIN
sobrescritura y STDOUT
con el descriptor de socket, mi solución inicial de hacer esto era recuperar la estructura sockaddr_in
, que contiene la información necesaria. Hacer esto con getsockname()
, sin embargo, está volviendo una estructura vacía, con todos los bits puestos a 0.
Cualquier idea de lo que está mal con mi enfoque? ¿Hay otros enfoques que puedo usar para recuperar el IP / Puerto?
Gracias
Solución
R .. señaló, se debe utilizar getpeername
. Tanto esa función y getsockname
toman un descriptor de archivo como primer argumento, no una corriente puntero (FILE *
). Uso fileno(stdin)
para obtener el descriptor de fichero para la entrada estándar (o difícil que el código de 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);
Ver un ejemplo completo aquí .
Otros consejos
Uso getpeername
. Sospecho que su problema es que getsockname
está regresando la información para su propio lado (local) de la cavidad, lo que probablemente está obligado a 0.0.0.0 (lo que significa que puede aceptar conexiones de cualquier interfaz).
Editar Creo que he encontrado el error real de la lectura del código. Esta línea está equivocado:
getsockname(stdin, &addr, sizeof(addr));
funciones El getsockname
y getpeername
toman un socklen_t *
(a puntero ) como su tercer argumento, no una size_t
. El compilador debe estar diciendo acerca de este error a menos que se olvidó de incluir un encabezado con el prototipo de getsockname
. Además, como ya se ha dicho, stdin
es incorrecta. Proveedores:
socklen_t len = sizeof addr;
getpeername(0, &addr, &len);
o (sólo C99):
getpeername(0, &addr, (socklen_t[1]){sizeof addr});
También debe comprobar el valor de retorno; si lo hiciera, vería que está volviendo errores.
Si necesita los datos para el cliente remoto, usted tiene que llamar getpeername () .