Can one reliably connect a TCP socket to itself?

蓝咒 提交于 2021-02-08 08:33:29

问题


I am wondering whether it is possible to reliably connect a TCP socket to itself -- that is, to get just one socket where whatever you send() on you receive back through recv(). I saw that this can happen (e.g., here, here, and here), but none of these posts explain how to do this programmatically and reliably (i.e., this is usually touted as a curiosity, rather than a feature one would use deliberately). I'm interested in a solution for Windows, Mac, and Linux.

Just for completeness, please let me explain why I'm interested in this. I'm writing a cloud-based application where servers can send messages to other servers, including themselves. Each server uses one socket to talk to other servers, and so, to unify the code and make certain threading issues simpler, it would be good if the server could talk to itself using just one socket as well.

EDIT: @Rufflewind suggested connecting to the loopback adapter. I tried that using the code below, both with and without the call to listen. In all cases, however, I got an error (either "Invalid argument" or "Operation not supported"). What am I doing wrong?

#include <iostream>
#include <netinet/tcp.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

void die(const char* const message) {
    perror(message);
    exit(0);
}

#define CHECK(operation,message) \
    if ((operation) != 0) \
        die(message)

int main(int argc, char* argv[]) {
    sockaddr_in local;
    local.sin_family = AF_INET;
    local.sin_port = htons(40000);
    inet_aton("127.0.0.1", &local.sin_addr);
    int sck = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    CHECK(bind(sck, (struct sockaddr *)&local, sizeof(local)), "Error while binding the socket to an address");
//    CHECK(listen(sck, 1), "Error while listening.");
    CHECK(connect(sck, (struct sockaddr *)&local, sizeof(local)), "Error while connecting the socket to self");
    std::cout << "Succeeded in connecting sockets!" << std::endl;
    const char* message = "ABCDEFGH";
    const size_t messageLength = ::strlen(message) + 1;
    const char* currentSend = message;
    ssize_t leftToSend = messageLength;
    while (leftToSend != 0) {
        const ssize_t sent = send(sck, currentSend, leftToSend, 0);
        if (sent == -1)
            die("Can't send.");
        currentSend += sent;
        leftToSend -= sent;
    }
    std::cout << "Sent the message!" << std::endl;
    char buffer[256];
    char* currentRead = buffer;
    size_t leftToRead = messageLength;
    while (leftToRead != 0) {
        const ssize_t read = recv(sck, currentRead, leftToRead, 0);
        if (read == -1)
            die("Can't read.");
        currentRead += read;
        leftToRead -= read;
    }
    std::cout << "Received message: " << buffer << std::endl;
    return 0;
}

回答1:


The most straightforward approach would be to bind to the loopback adapter. Just listen to 127.0.0.1 on some arbitrary port and the connect to that.

The problem with this approach is that the port is global on the machine, so that means other programs can connect to it too, and if you have multiple programs you might run into conflicts or conceivably exhaust all the possible ports.

Another approach is to use Unix domain sockets, but this is not supported on Windows.



来源:https://stackoverflow.com/questions/37224719/can-one-reliably-connect-a-tcp-socket-to-itself

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!