简体   繁体   中英

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? Say, I have the socket file descriptor, and the remote ip. Can I simply inspect if the remote ip is 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 ). 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; 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. A machine can have multiple IPs assigned to it, and multiple IPs on the same machine can communicate with each other.

如果你已经拥有远程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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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