2012-01-03 15 views
10

Usando las API de programación de socket (por ejemplo, socket(), connect(), accept() ...), ¿cómo puedo saber si hay una conexión TCP entre dos procesos en la misma máquina? Diga, tengo el descriptor de archivo de socket y la ip remota. ¿Puedo simplemente inspeccionar si la dirección IP remota es 127.0.0.1?¿Cómo saber si una conexión TCP se encuentra entre dos procesos en la misma máquina?

+1

Puede intentar llamar 'getsockname()' y 'getpeername()' en el mismo socket luego comparar las direcciones devueltas. –

+0

Si se excluyen varios dispositivos de red en la misma máquina, ¿podría verificar la dirección MAC en cada extremo de la conexión y ver si son iguales? – abelenky

+0

Normalmente no hay un encabezado MAC, y por lo tanto no hay una dirección MAC, utilizada en el bucle invertido. –

Respuesta

2

Aquí está el enfoque que he utilizado. La idea es intentar vincular a un oyente con esa dirección IP y usar los códigos de falla/éxito para decidir si la dirección es local.

No estoy diciendo que esto sea particularmente eficiente, pero debería ser bastante confiable, y para mi aplicación fue apropiado.

#include <sys/socket.h> 
#include <errno.h> 
/* ...probably need some other headers I am forgetting... */ 

int 
is_local(const struct sockaddr *addr, socklen_t addr_len) 
{ 
    const char *func = "is_local()"; 
    int result = 0; 

    int tmp = socket(addr->sa_family, SOCK_STREAM, 0); 
    if (tmp < 0) { 
     printf("%s: socket(%d,SOCK_STREAM,0) failed, errno %d\n", 
       func, addr->sa_family); 

     goto out; 
    } 

    /* If bind() succeeds, or if it fails because the address is in 
     use, then the address must be local to this system. */ 
    if (bind(tmp, addr, addr_len) < 0) { 
     if (errno == EADDRINUSE) 
      result = 1; 
     else if (errno == EADDRNOTAVAIL) 
      ; /* do nothing; address is remote */ 
     else 
      printf("%s: bind() unexpected error %d\n", func, errno); 
    } 
    else { 
     result = 1; 
    } 

    close(tmp); 

out: 
    return result; 
} 

Se llaman así:

struct sockaddr_storage client_addr; 
socklen_t client_addr_len = sizeof(client_addr); 
int fd = accept(listener, &client_addr, &client_addr_len); 

if (is_local((struct sockaddr *)&client_addr, client_addr_len)) 
    /* peer is local */ 
+0

¡Me gusta este enfoque! – flyingbin

7

No hay una forma realmente confiable de determinar esto: puede conectarse a procesos locales utilizando una dirección IP enrutada globalmente (es decir, los procesos locales pueden usar direcciones IP distintas de 127.0.0.1). También es posible que un proceso se ejecute en una máquina virtual diferente en el mismo hardware físico, si se encuentra en un entorno virtualizado.

Nótese, sin embargo, que si el IP remoto (a través de getpeername) o IP local (a través de getsockname) comienza con 127 (incluyendo 127.0.0.1), entonces es de hecho una conexión local; sin embargo, no puede descartar la posibilidad de que sea una conexión local si se trata de un par de direcciones diferente.

2

Si ya tiene la dirección IP remota, puede verificar si es la dirección de bucle invertido o si es la dirección IP del host, porque, como señala cnicutar, no tiene que estar sobre el bucle invertido dirección para ser una conexión local.

3

Uso getsockname() y getpeername() es posible recuperar los dos períodos de investigación asociados a la conexión, a continuación, utilizar gethostname() y gethostbyname() (u otras APIs específicas de la plataforma, como GetAdaptersInfo() y GetAdapterAddresses() en Windows) para determinar las direcciones IP que pertenecen a la máquina local, a continuación, puede comparar las IP de conexión con las IP de la máquina local para ver si ambas coinciden. Una máquina puede tener múltiples direcciones IP asignadas, y múltiples direcciones IP en la misma máquina se pueden comunicar entre sí.

Cuestiones relacionadas