Как узнать, существует ли соединение TCP между двумя процессами на одном компьютере?

Используя API-интерфейсы программирования сокетов (например, socket(), connect(), accept()...), как я могу узнать, связано ли TCP-соединение между двумя процессами на одном компьютере? Скажем, у меня есть дескриптор файла сокета и удаленный ip. Могу ли я просто проверить, удаленный IP-адрес равен 127.0.0.1?

Ответ 1

Вот такой подход, который я использовал. Идея состоит в попытке связать слушателя с этим IP-адресом и использовать коды отказа/успеха, чтобы определить, является ли адрес локальным.

Я не утверждаю, что это особенно эффективно, но оно должно быть достаточно надежным, и для моего приложения это было уместно.

#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;
}

Вы называете это следующим образом:

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 */

Ответ 2

Нет надежного способа определить это - вы можете подключаться к локальным процессам с использованием глобального маршрутизируемого IP-адреса (то есть локальные процессы могут использовать IP-адреса, отличные от 127.0.0.1). Также возможно выполнение процесса на другой виртуальной машине на одном физическом оборудовании, если вы находитесь в виртуализованной среде.

Обратите внимание, что если удаленный IP (через getpeername) или локальный IP (через getsockname) начинается с 127 (включая 127.0.0.1), то это действительно локальное соединение; однако вы не можете исключить возможность того, что это может быть локальное соединение, если оно отличается от пары адресов.

Ответ 3

Используйте getsockname() и getpeername() для восстановления двух IP-адресов, связанных с соединением, затем используйте gethostname() и gethostbyname() (или другие API-интерфейсы платформы, такие как GetAdaptersInfo() и GetAdapterAddresses() в Windows), чтобы определить IP-адреса, принадлежащие локальной машине, тогда вы можете сравнить IP-соединения с IP-адресами локальных компьютеров, чтобы узнать, совпадают ли они. У машины может быть назначено несколько IP-адресов, и несколько IP-адресов на одном компьютере могут взаимодействовать друг с другом.

Ответ 4

Если у вас уже есть удаленный IP-адрес, вы можете проверить, является ли он петлевым адресом или если он является IP-адресом хоста, потому что, как указывает cnicutar, он не должен быть над адресом loopback для локального соединения.