Frage

Ich bin die Implementierung einer einfachen Service-Datagramme über Unix lokale Steckdosen (AF_UNIX Adresse der Familie, das heißt nicht UDP ) verwenden. Der Server ist mit einer öffentlichen Adresse gebunden, und es empfängt Anforderungen gut. Leider, wenn es um die Beantwortung zurückkommt, versagt sendto es sei denn, der Kunde zu gebunden ist. (Der gemeinsame Fehler ist Transport endpoint is not connected).

Die Bindung an einen zufälligen Namen (Dateisystem-basierte oder abstrakt) arbeitet. Aber ich möchte, dass vermeiden: Wer bin ich die Namen zu gewährleisten, nahm ich nicht kollidieren

Der Modus Dokumentation Unix-Sockets-Stream sagen uns, dass ein abstrakter Name in connect Zeit zu ihnen zugewiesen wird, wenn sie eine noch nicht haben. Ist ein solches Feature für Datagramm orientierte Steckdosen?

War es hilfreich?

Lösung

Ich gehe davon aus, dass Sie Linux laufen; Ich weiß nicht, ob dieser Rat zu SunOS oder jede UNIX gilt.

Zuerst die Antwort: Nach der Buchse () und vor dem connect () oder erste sendto (), versuchen Sie diesen Code hinzu:

struct sockaddr_un me;
me.sun_family = AF_UNIX;
int result = bind(fd, (void*)&me, sizeof(short));

Nun wird die Erklärung: die der Unix (7) Manpage dies sagt:

  

Wenn eine Steckdose angeschlossen ist und   nicht bereits eine lokale Adresse einer   eindeutige Adresse in der Zusammenfassung   Namensraum wird generiert   automatisch.

Leider liegt die Mann-Seite.

Die Untersuchung des Linux-Quellcode , sehen wir, dass unix_dgram_connect () nur Anrufe unix_autobind (), wenn SOCK_PASSCRED in den Sockel Flags gesetzt ist. Da ich nicht weiß, was SOCK_PASSCRED ist, und es ist jetzt 01.00 Uhr, muss ich für eine andere Lösung suchen.

unix_bind , ich bemerke, dass unix_bind Anrufe unix_autobind wenn der übergebene Größe gleich „sizeof (kurz)“. Somit wird die Lösung über.

Viel Glück und guten Morgen.

Rob

Andere Tipps

Die Unix (7) Manpage I verwiesen hatte diese Informationen über autobind UNIX-Sockets :

  

Wenn ein bind (2) Aufruf gibt addrlen als sizeof (sa_family_t) oder die SO_PASSCRED Socket-Option wurde für einen Socket angegeben, die nicht explizit an eine Adresse gebunden wurde, dann ist die Buchse auf eine abstrakte Adresse autobound wird.

Aus diesem Grund ist der Linux-Kernel die Adresse Länge gleich sizeof (short) überprüft, weil sa_family_t ein kurz ist. Die andere Unix (7) man-Seite von Robs große Antwort verwiesen sagt, dass Client-Sockets werden immer auf connect autobound, sondern weil SOCK_DGRAM Steckdosen verbindungslos sind (trotz sie auffordern verbinden) Ich glaube, dies gilt nur für SOCK_STREAM Sockets.

Beachten Sie auch, dass, wenn Sie Ihre eigenen abstrakten Namespace Socket-Namen liefern, die Adresse der Buchse in diesem Namensraum durch die zusätzlichen Bytes in sun_path gegeben wird, die durch die angegebene Länge der Adressstruktur abgedeckt ist.

struct sockaddr_un me;
const char name[] = "\0myabstractsocket";
me.sun_family = AF_UNIX;
// size-1 because abstract socket names are not null terminated
memcpy(me.sun_path, name, sizeof(name) - 1);
int result = bind(fd, (void*)&me, sizeof(me.sun_family) + sizeof(name) - 1);

sendto () soll ebenfalls die Adressenlänge begrenzen, und übergibt sizeof nicht (sockaddr_un).

Ein bisschen eine späte Antwort, aber für wen auch immer findet diese Google verwenden wie ich. Rob Adams Antwort hat mir geholfen, die ‚echte‘ Antwort auf diese Frage zu bekommen. Verwenden Sie einfach eingestellt (Stufe SO_SOCKET siehe man 7 unix) SO_PASSCRED 1. Keine Notwendigkeit für eine dumme binden setzen

Ich habe diese in PHP, aber es hat nicht SO_PASSCRED definiert (dumm PHP). Es funktioniert immer noch, obwohl, wenn Sie es selbst zu definieren. Auf meinem Computer hat es den Wert von 16, und ich rechne damit, dass es recht portabel funktioniert.

Ich bin mir nicht so sicher, ob ich verstehe Ihre Frage vollständig, aber hier ist ein Datagramm Implementierung eines Echo-Server ich gerade schrieb. Sie können sehen, der Server an den Client auf dem gleichen IP / PORT reagiert es aus gesendet wurde.

Hier ist der Code

Zuerst wird der Server (Hörer)

from socket import *
import time
class Listener:
    def __init__(self, port):
        self.port = port
        self.buffer = 102400

    def listen(self):

        sock = socket(AF_INET, SOCK_DGRAM)
        sock.bind(('', self.port))

        while 1:
            data, addr = sock.recvfrom(self.buffer)
            print "Received: " + data
            print "sending to %s" % addr[0]
            print "sending data %s" % data
            time.sleep(0.25)
            #print addr # will tell you what IP address the request came from and port
            sock.sendto(data, (addr[0], addr[1]))
            print "sent"
        sock.close()

if __name__ == "__main__":
    l = Listener(1975)
    l.listen()

Und nun der Kunde (Absender), die die Antwort der Zuhörer

empfängt
from socket import *
from time import sleep
class Sender:
    def __init__(self, server):
       self.port = 1975
       self.server = server
       self.buffer = 102400

    def sendPacket(self, packet):
        sock = socket(AF_INET, SOCK_DGRAM)
        sock.settimeout(10.75)


        sock.sendto(packet, (self.server, int(self.port)))

        while 1:
            print "waiting for response"
            data, addr = sock.recvfrom(self.buffer)
            sock.close()
            return data



if __name__ == "__main__":
        s = Sender("127.0.0.1")
        response = s.sendPacket("Hello, world!")
        print response
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top