Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/apache-flex/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets 可以可靠地将TCP套接字连接到自身吗?_Sockets_Tcp - Fatal编程技术网

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

Sockets 可以可靠地将TCP套接字连接到自身吗?,sockets,tcp,Sockets,Tcp,我想知道是否有可能将TCP套接字可靠地连接到自身——也就是说,只需要一个套接字,就可以在其中接收通过recv()发送的内容。我看到这是可能发生的(例如,,,和),但这些帖子都没有解释如何通过编程和可靠地实现这一点(也就是说,这通常被吹捧为好奇,而不是故意使用的特性)。我对Windows、Mac和Linux的解决方案感兴趣 为了完整起见,请让我解释一下为什么我对这个感兴趣。我正在编写一个基于云的应用程序,其中服务器可以向其他服务器发送消息,包括它们自己。每个服务器都使用一个套接字与其他服务器进行通

我想知道是否有可能将TCP套接字可靠地连接到自身——也就是说,只需要一个套接字,就可以在其中接收通过recv()发送的内容。我看到这是可能发生的(例如,,,和),但这些帖子都没有解释如何通过编程和可靠地实现这一点(也就是说,这通常被吹捧为好奇,而不是故意使用的特性)。我对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;
}
#包括
#包括
#包括
#包括
#包括
#包括
无效骰子(常量字符*常量消息){
佩罗尔(信息);
出口(0);
}
#定义检查(操作、消息)\
如果((操作)!=0)\
死亡(讯息)
int main(int argc,char*argv[]){
当地的sockaddr_;
local.sin_family=AF_INET;
local.sin_port=htons(40000);
inet_aton(“127.0.0.1”和local.sin_addr);
int sck=套接字(AF_INET、SOCK流、IPPROTO_TCP);
检查(bind(sck,(struct sockaddr*)&local,sizeof(local)),“将套接字绑定到地址时出错”);
//检查(侦听(sck,1),“侦听时出错”);
检查(connect(sck,(struct sockaddr*)&local,sizeof(local)),“将套接字连接到self时出错”);

std::cout最直接的方法是绑定到环回适配器。只需在某个任意端口上收听
127.0.0.1
,然后连接到该端口

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


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

最简单的方法是绑定到环回适配器。只需在某个任意端口上收听
127.0.0.1
,然后连接到该端口即可

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


另一种方法是使用Unix域套接字,但这在Windows上不受支持。

你的意思是连接到echo服务器吗?@MartinJames我想到了这一点:是的,类似于这样,不过如果不涉及外部进程会更好(也就是说,您不需要在单独的线程中运行真正的echo服务器——理想情况下,它将由TCP堆栈处理,因为套接字将具有相同的传出和传入地址)“你的意思是,比如说,连接到一个echo服务器?”马丁尼这样想:是的,类似这样的事情,不过如果没有涉及到外部进程会更好(也就是说,您不需要在单独的线程中运行真正的echo服务器——理想情况下,它将由TCP堆栈处理,因为套接字将具有相同的传出和传入地址)。谢谢。我已经用一些示例代码更新了我的帖子,在其中我尝试了,但没有成功。如果你能指出我做错了什么,我将非常感激。另外,请注意,我希望我能有一个套接字“自己”完成所有循环--也就是说,不需要有人读取数据然后写回。如果最坏的情况发生,我想我总是可以有一个单独的环回线程;但是,我只是希望我可以有一个由系统提供的“自循环套接字”。你的代码在我的机器(Linux)上似乎运行得很好.Hmm,现在我在Linux上试过了,它确实可以工作。最初我使用的是Mac OS X,但它不起作用。因此,似乎在我感兴趣的所有平台上都没有可移植的方法来实现这一点。无论如何,感谢你的帮助!连接到环回的方式有点非传统。正如你所说,最可移植的方法需要第二种线程作为客户端进行回音。谢谢。我已经用一些示例代码更新了我的帖子,在其中我尝试了,但没有成功。如果你能指出我做错了什么,我将非常感谢。另外,请注意,我希望我能有一个套接字“自己”完成所有循环--也就是说,不需要有人读取数据然后写回。如果最坏的情况发生,我想我总是可以有一个单独的环回线程;但是,我只是希望我可以有一个由系统提供的“自循环套接字”。你的代码在我的机器(Linux)上似乎运行得很好.Hmm,现在我在Linux上试过了,它确实可以工作。最初我使用的是Mac OS X,但它不起作用。因此,似乎在我感兴趣的所有平台上都没有可移植的方法来实现这一点。无论如何,感谢你的帮助!连接到环回的方式有点非传统。正如你所说,最可移植的方法需要第二种线程充当执行回显的客户端。