可以将TCP套接字可靠地连接到自身吗?

时间:2016-05-14 09:00:10

标签: sockets tcp

我想知道是否可以将TCP套接字可靠地连接到自身 - 也就是说,只需要一个套接字就可以通过recv()收到您发送的任何内容()。我看到这可能发生(例如,hereherehere),但这些帖子都没有解释如何以编程方式可靠地执行此操作(即,这通常被吹捧为好奇心,而不是故意使用的特征。我对Windows,Mac和Linux的解决方案感兴趣。

为了完整起见,请让我解释为什么我对此感兴趣。我正在编写一个基于云的应用程序,服务器可以将消息发送到其他服务器,包括他们自己。每个服务器使用一个套接字与其他服务器通信,因此,为了统一代码并使某些线程问题更简单,如果服务器也可以仅使用一个套接字与自己对话,那将是一件好事。

编辑: @Rufflewind建议连接到环回适配器。我尝试使用下面的代码,无论有没有调用听。但是,在所有情况下,我都会收到错误("无效参数"或"操作不受支持")。我做错了什么?

#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 个答案:

答案 0 :(得分:0)

最直接的方法是绑定到环回适配器。只需在某个任意端口上听127.0.0.1并连接到该端口。

这种方法的问题是端口在机器上是全局的,这意味着其他程序也可以连接到它,如果你有多个程序,你可能会遇到冲突或可能会耗尽所有可能的端口。

另一种方法是使用Unix域套接字,但Windows不支持此功能。