如何确定TCP连接是否在同一台计算机上的两个进程之间?

10
使用套接字编程API(例如:socket()、connect()、accept()等),我该如何知道TCP连接是否在同一台计算机上的两个进程之间?假设我有套接字文件描述符和远程IP地址,我能否简单检查远程IP地址是否为127.0.0.1?

1
你可以尝试在同一个套接字上调用 getsockname()getpeername(),然后比较返回的地址。 - Captain Obvlious
除了在同一台计算机上禁用多个网络设备,您是否能够检查连接的每端的 MAC 地址,并查看它们是否相同? - abelenky
通常情况下,环回接口上没有MAC头,因此也不会使用MAC地址。 - jørgensen
所以,听起来像是:如果没有MAC地址==>回环。如果存在MAC地址,则比较它们;如果相等==>回环;如果不同,则可能(但不确定)是远程连接。 - abelenky
4个回答

7

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

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


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

2

如果您已经获取了远程IP地址,您可以检查它是否是环回地址或主机的IP地址。正如cnicutar所指出的那样,它不必通过环回地址来进行本地连接。


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接