Как узнать, находится ли TCP-соединение между двумя процессами на одном компьютере? - PullRequest
10 голосов
/ 04 января 2012

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

Ответы [ 4 ]

7 голосов
/ 04 января 2012

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

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

3 голосов
/ 04 января 2012

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

2 голосов
/ 04 января 2012

Вот подход, который я использовал. Идея состоит в том, чтобы попытаться привязать слушателя к этому 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 голосов
/ 04 января 2012

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

...