如何知道TCP连接是否在同一台机器上的两个进程之间?

时间:2012-01-03 21:28:36

标签: c++ c sockets tcp

使用套接字编程API(例如,socket(),connect(),accept()...),如何知道TCP连接是否在同一台机器上的两个进程之间?说,我有套接字文件描述符和远程ip。我可以简单地检查远程IP是否为127.0.0.1?

4 个答案:

答案 0 :(得分:7)

没有真正可靠的方法来确定这一点 - 您可以使用全局路由的IP地址连接到本地进程(即,本地进程可以使用127.0.0.1以外的IP)。如果您处于虚拟化环境中,则进程也可以在同一物理硬件上的不同虚拟机中运行。

但请注意,如果远程IP(通过getpeername)或本地IP(通过getsockname)以127(包括127.0.0.1)开头,那么它是确实是当地的联系;但是,如果它是一对不同的地址,你不能排除可能是本地连接的可能性。

答案 1 :(得分:3)

使用getsockname()getpeername()来检索与该连接关联的两个IP,然后使用gethostname()gethostbyname()(或其他特定于平台的API,例如{{1} Windows上的{和GetAdaptersInfo())确定属于本地计算机的IP,然后您可以将连接IP与本地计算机IP进行比较,以查看它们是否匹配。一台机器可以分配多个IP,同一台机器上的多个IP可以相互通信。

答案 2 :(得分:2)

如果你已经拥有远程ip地址,你可以检查它是否是环回地址,或者它是否是主机的ip地址,因为正如cnicutar指出的那样,它不必超过环回地址成为本地连接。

答案 3 :(得分:2)

这是我使用过的方法。我们的想法是尝试将侦听器绑定到该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 */