2016-05-03 19 views
1

Dies ist das erste Mal, dass ich mit Unix-Sockets programmieren, also verzeihen Sie die dummen Fehler. Ich habe die folgende Funktion geschrieben, um einen Unix-Socket zu erstellen.Unix Socket Dateiname Fehler

int create_server_unix_socket(const string& socket_path) { 

    // STEP 1 : socket() 
    int unix_socket = socket(AF_UNIX, SOCK_STREAM, 0); 
    if (unix_socket == -1) { 
     throw std::runtime_error {"Error occured in socket() call : "s + 
      string(std::strerror(errno))}; 
    } 

    // STEP 2 : bind(), setup the address structures for bind() 
    sockaddr_un local_address; 
    local_address.sun_family = AF_UNIX; 
    std::strcpy(local_address.sun_path, socket_path.c_str()); 

    // unlink from before 
    unlink(socket_path.c_str()); 

    // STEP 2 : bind() 
    size_t length = socket_path.size() + sizeof(local_address.sun_family); 
    if (::bind(unix_socket, reinterpret_cast<sockaddr*>(&local_address), 
       length) == -1) { 
     throw std::runtime_error {"Error occured in bind() call : "s + 
      string(strerror(errno))}; 
    } 

    // STEP 3 : listen() 
    if (listen(unix_socket, 5) == -1) { 
     throw std::runtime_error {"Error occured in listen() call : "s + 
      string(strerror(errno))}; 
    } 

    return unix_socket; 
} 

Aber wenn ich versuche, und eine Buchse schaffen wie so

create_server_unix_socket("./unix_socket"s); 

Die Datei, die in dem aktuellen Arbeitsverzeichnis erstellt wird, ist unix_socke statt unix_socket und in der Tat dies geschieht zu einem beliebigen Namen, die ich versuche, . Wenn ich unix_socket_longer_name versuche, ist die produzierte Datei unix_socket_longer_nam. Ich betreibe dies auf einem Mac OS X (Version 10.11.4).

Irgendwelche Ideen zu was ich falsch mache? Auch wenn Sie etwas schrecklich falsch in meinem Code bemerken, lass es mich wissen! Ich schrieb dies, indem ich die man-Seiten konsultierte und ich bin mir nicht ganz sicher, ob ich es richtig gemacht habe. Vielen Dank!

HINWEIS: Ich kompiliere dies mit C++ 14, müssten Sie den Namespace std::literals::string_literals importieren, um diese Arbeit zu machen. Fügen Sie using namespace std::literals::string_literals an den Anfang Ihres Codes.

Antwort

2

Lassen Sie uns einen Blick auf den Mann Seite von bind

int bind(int sockfd, const struct sockaddr *addr, 
      socklen_t addrlen); 

Der dritte Parameter ist die addrlen

addrlen die Größe in Byte angibt, von der Adressstruktur hingewiesen zu durch addr.

Also, was Sie passieren sollten, ist sizeof local_address. Stattdessen haben Sie length übergeben, also socket_path.size() + sizeof(local_address.sun_family). Diese Größe ist fast genug, aber es gibt keinen Platz für den Nullabschluss und ignoriert die Möglichkeit, dass sockaddr_un Padding enthalten kann.

Wenn Sie wirklich eine Länge übergeben wollen, die den Pfad entspricht nicht der Größe des local_address, könnten Sie offsetof verwenden:

length = offsetof(sockaddr_un, sun_path) + socket_path.size() + 1; 

Aber ich habe nicht einen Vorteil, um es über einfach sehen vorbei sizeof local_address .

+0

Ich dachte, das war das Problem! Ich habe es direkt von den man-Seiten gemacht, bin aber auf meine Entscheidung zurückgegangen, als ich hier http://beej.us/guide/bgipc/output/html/multipage/unixsock.html angeschaut habe und der Autor schien die Länge zu benutzen, die ich benutzt habe im Code-Schnipsel oben! – Curious

+1

@Curious Ich vermute, dass Code wahrscheinlich von plattformspezifischen Verhalten abhängt und in einigen Implementierungen gut funktionieren kann. Hat mein Vorschlag das Problem behoben? – user2079303

+0

Ja, tat es! Ich hatte eine andere Frage, aber ich denke, dass ich das bald als eine andere Frage stellen werde. Vielen Dank! – Curious