简体   繁体   English

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

[英]How to know if a TCP connection is between two processes on the same machine?

Using socket programming APIs (eg, socket(), connect(), accept() ...), how can I know if a TCP connection is between two processes on the same machine? 使用套接字编程API(例如,socket(),connect(),accept()...),我怎么知道TCP连接是否在同一台机器上的两个进程之间? Say, I have the socket file descriptor, and the remote ip. 说,我有套接字文件描述符和远程ip。 Can I simply inspect if the remote ip is 127.0.0.1? 我可以简单地检查远程IP是否为127.0.0.1?

There's no really reliable way to determine this - you can connect to local processes using a globally routed IP address (ie, local processes can use IPs other than 127.0.0.1 ). 没有真正可靠的方法来确定这一点 - 您可以使用全局路由的IP地址连接到本地进程(即,本地进程可以使用127.0.0.1以外的IP)。 It's also possible for a process to run in a different virtual machine on the same physical hardware, if you're in a virtualized environment. 如果您处于虚拟化环境中,那么进程也可以在同一物理硬件上的不同虚拟机中运行。

Note, however, that if the remote IP (via getpeername ) or local IP (via getsockname ) starts with 127 (including 127.0.0.1 ), then it is indeed a local connection; 但请注意,如果远程IP(通过getpeername )或本地IP(通过getsockname )以127 (包括127.0.0.1 )开头,那么它确实是本地连接; however, you can't rule out the possibility that it might be a local connection if it's a different pair of addresses. 但是,如果它是一对不同的地址,则不能排除它可能是本地连接的可能性。

Use getsockname() and getpeername() to retreive the two IPs associated with the connection, then use gethostname() and gethostbyname() (or other platform-specific APIs, like GetAdaptersInfo() and GetAdapterAddresses() on Windows) to determine the IPs that belong to the local machine, then you can compare the connection IPs to the local machine IPs to see if they both match. 使用getsockname()getpeername()来检索与该连接关联的两个IP,然后使用gethostname()gethostbyname() (或其他特定于平台的API,如Windows上的GetAdaptersInfo()GetAdapterAddresses() )来确定IP属于本地计算机,然后您可以将连接IP与本地计算机IP进行比较,以查看它们是否匹配。 A machine can have multiple IPs assigned to it, and multiple IPs on the same machine can communicate with each other. 一台机器可以分配多个IP,同一台机器上的多个IP可以相互通信。

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

Here is the approach I have used. 这是我使用的方法。 The idea is to attempt to bind a listener to that IP address and use the failure/success codes to decide whether the address is local. 我们的想法是尝试将侦听器绑定到该IP地址,并使用失败/成功代码来确定该地址是否是本地的。

I am not claiming this is particularly efficient, but it should be fairly reliable, and for my application it was appropriate. 我并不是说这个效率特别高,但它应该相当可靠,对我的应用来说这是合适的。

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

You call it like this: 你这样称呼它:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM