2016-05-14 10 views
1

Ich frage mich, ob es möglich ist, einen TCP-Socket zuverlässig mit sich selbst zu verbinden - das heißt, nur einen Socket zu bekommen, wo immer Sie senden() auf Sie über recv() zurück erhalten. Ich habe gesehen, dass das passieren kann (zB here, here und here), aber keiner dieser Beiträge erklärt, wie man das programmatisch und zuverlässig macht (dh, das wird normalerweise als Kuriosum angepriesen und nicht als Feature, das man absichtlich benutzen würde) . Ich bin an einer Lösung für Windows, Mac und Linux interessiert.Kann man einen TCP-Socket zuverlässig mit sich selbst verbinden?

Nur zur Vollständigkeit, bitte lassen Sie mich erklären, warum mich das interessiert. Ich schreibe eine Cloud-basierte Anwendung, bei der Server Nachrichten an andere Server senden können, einschließlich sich selbst. Jeder Server verwendet einen Socket, um mit anderen Servern zu kommunizieren. Um also den Code zu vereinheitlichen und bestimmte Threading-Probleme zu vereinfachen, wäre es gut, wenn der Server auch mit nur einem Socket mit sich selbst sprechen könnte.

EDIT: @Rufflewind schlug vor, eine Verbindung zum Loopback-Adapter herzustellen. Ich habe das mit dem unten stehenden Code versucht, sowohl mit als auch ohne den Anruf zu hören. In allen Fällen habe ich jedoch einen Fehler erhalten (entweder "Ungültiges Argument" oder "Operation nicht unterstützt"). Was mache ich falsch?

#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

Sie meinen, wie, Verbindung zu einem Echo-Server? –

+0

@MartinJames Ich dachte daran: http://thecodelesscode.com/case/28 – Aaron3468

+0

Ja, so etwas, obwohl es besser wäre, wenn es keine externen Prozesse beteiligt sind (dh, Sie müssen keine echte ausführen Echo-Server in einem separaten Thread - im Idealfall würde alles vom TCP-Stack behandelt werden, da der Socket die gleichen ausgehenden und eingehenden Adressen haben würde. – Boris

Antwort

0

Der einfachste Weg wäre, an den Loopback-Adapter zu binden. Hören Sie einfach 127.0.0.1 auf einem beliebigen Port und die Verbindung zu diesem.

Das Problem bei diesem Ansatz ist, dass der Port auf der Maschine global ist, so bedeutet das andere Programme zu ihm herstellen können, und wenn Sie mehrere Programme haben Sie in Konflikte führen könnte oder möglicherweise alle möglichen Ports erschöpfen .

Ein anderer Ansatz besteht darin, Unix-Domain-Sockets zu verwenden, aber dies wird unter Windows nicht unterstützt.

+0

Danke. Ich habe meinen Beitrag mit einem Beispielcode aktualisiert, in dem ich das versucht habe, aber es hat nicht funktioniert. Ich wäre sehr dankbar, wenn du aufzeigen könntest, was ich falsch mache. – Boris

+0

Außerdem habe ich gehofft, dass ich nur einen ** Socket haben könnte, der das ganze Looping "von selbst" macht - das heißt, ohne dass jemand die Daten lesen und dann zurückschreiben muss. Im schlimmsten Fall kann ich immer einen separaten Loopback-Thread haben; Ich hatte jedoch nur gehofft, ich könnte einen "Self-Looping-Socket" vom System bekommen. – Boris

+0

Ihr Code scheint auf meinem Rechner (Linux) einwandfrei zu funktionieren. – Rufflewind

Verwandte Themen