2017-10-29 2 views
0

Es ist etwas ich nicht arround meinen Kopf bekommen. Ich habe einen Unix-Datagramm-Socket mit erstellt:UNIX-Datagram-Socket-Rück Daten an den Absender

self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) 
self.socket.bind(SOCKET_FILE) 

später im Code i-Nachrichten an die Buchse mit

data, addr = self.socket.recvfrom(4096) 

geschrieben erhalte aber Adr erscheint None die ganze Zeit zu sein. Aber ich brauche es, um eine Antwort zu senden.
Wie kann ich erreichen, zurück an den Absender mit Unix-Datagramm-Sockets zu schreiben?

Vielen Dank für Ihre Antworten

+1

Sie haben uns den Client-Code nicht angezeigt, aber ich denke, der Client ruft Bind nicht für den Socket auf, der zum Senden von Nachrichten verwendet wird. –

Antwort

1

Angenommen, wir haben einen Server:

# server.py 
import os 
import socket 

SOCKET_FILE = "mysocket-server" 
s = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) 
s.bind(SOCKET_FILE) 
data, addr = s.recvfrom(4096) 
s.close() 
os.unlink(SOCKET_FILE) 
print(data, addr) 

Wenn ein Client eine Verbindung und sendet eine Nachricht, ohne seinen eigenen Namen an die Buchse Bindung, etwa so:

# client.py 
import socket 

SOCKET_FILE = "mysocket-server" 
sk = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) 
sk.sendto("hello", SOCKET_FILE) 
sk.close() 

dann wird die Nachricht anonym ohne Adresse gebunden auf der Client-Seite (dh mit addr == None) gesendet. Beachten Sie, dass sich dies von IP-Datagramm-Sockets unterscheidet, die automatisch an eine neue Adresse (d. H. Hostadresse und Portnummer) gebunden werden, sobald Sie Daten senden.

Für solche anonymen Nachrichten über Unix Datagramm-Sockets, hat der Kunde keine Adresse zugewiesen, und es gibt keinen Mechanismus, mit dem der Server Rückgabedaten an den Absender schicken.

Die einfachste Lösung ist für die Kunden seine eigenen privaten Namen an die Steckdose zu binden:

# client2.py 
import os 
import socket 

SERVER_FILE = "mysocket-server" 
CLIENT_FILE = "mysocket-client" 

sk = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) 
sk.bind(CLIENT_FILE) 
sk.sendto("hello", SERVER_FILE) 
data, addr = sk.recvfrom(4096) 
print(data,addr) 
sk.close() 
os.unlink(CLIENT_FILE) 

Dann den folgenden modifizierten Server mit:

# server2.py 
import os 
import socket 

SOCKET_FILE = "mysocket-server" 
s = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) 
s.bind(SOCKET_FILE) 

data, addr = s.recvfrom(4096) 
if addr is not None: 
s.sendto("world", addr) 
print(data, addr) 

s.close() 
os.unlink(SOCKET_FILE) 

Sie, dass Zwei-Wege sehen Kommunikation ist möglich.

Unter Linux gibt es eine „abstrakten Namensraum“ Erweiterung (siehe unix(7) Manpage), die der Client bedeutet, kann auch mit sk.bind(""), wie so in einen leeren Namen binden:

# client3.py 
import socket 

SERVER_FILE = "mysocket-server" 

sk = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) 
sk.bind("") 
sk.sendto("hello", SERVER_FILE) 
data, addr = sk.recvfrom(4096) 
print(data,addr) 
sk.close() 

Dies bindet automatisch den Client eine neue "abstrakte Socket-Adresse", die genau das nachahmt, was IP-Datagramm-Sockets bereits tun.

Alternativ können Sie auch SOCK_SEQPACKET anstelle von SOCK_DGRAM verwenden. Dadurch wird automatisch erstellt eine bidirektionale Verbindung (wie SOCK_STREAM), sondern bewahrt die Nachrichtengrenzen (wie SOCK_DATAGRAM). Hier ist ein Server, der Verbindungen von Clients in einer Schleife annimmt und zwei Pakete von jedem Client empfängt und beantwortet.

# server4.py 
import os 
import socket 

SOCKET_FILE = "mysocket-server" 
s = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET) 
s.bind(SOCKET_FILE) 
s.listen(5) 

try: 
while True: 
    (t, _) = s.accept() 
    print(t.recv(4096)) 
    t.send("sun") 
    print(t.recv(4096)) 
    t.send("moon") 
    t.close() 
finally: 
os.unlink(SOCKET_FILE) 

Der folgende Client zeigt, dass die Antwortpakete getrennt gehalten werden:

# client4.py 
import socket 

SERVER_FILE = "mysocket-server" 

sk = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET) 
sk.connect(SERVER_FILE) 
sk.send("hello") 
sk.send("goodbye") 
print(sk.recv(4096)) 
print(sk.recv(4096)) 
sk.close() 

Hier server4.py ist kein großes Server-Design, da ein schlecht benommen Client kann blockieren, verhindert, dass der Server vom Dienst andere Kunden.Ein echter Server verwendet möglicherweise separate Arbeitsthreads, um angesichts der langsamen Clients weiter zu arbeiten.

Verwandte Themen