Programme hängt während Buchse Interaktion
-
04-10-2019 - |
Frage
Ich habe zwei Programme, sendfile.py und recvfile.py, die angeblich zu interagieren, um eine Datei über das Netzwerk zu senden. Sie kommunizieren über TCP-Sockets. Die Kommunikation soll so etwas gehen:
sender =====filename=====> receiver
sender <===== 'ok' ======= receiver
or
sender <===== 'no' ======= receiver
if ok:
sender ====== file ======> receiver
Ich habe
Der Sender und Empfänger-Code ist hier:
Sender:
import sys
from jmm_sockets import *
if len(sys.argv) != 4:
print "Usage:", sys.argv[0], "<host> <port> <filename>"
sys.exit(1)
s = getClientSocket(sys.argv[1], int(sys.argv[2]))
try:
f = open(sys.argv[3])
except IOError, msg:
print "couldn't open file"
sys.exit(1)
# send filename
s.send(sys.argv[3])
# receive 'ok'
buffer = None
response = str()
while 1:
buffer = s.recv(1)
if buffer == '':
break
else:
response = response + buffer
if response == 'ok':
print 'receiver acknowledged receipt of filename'
# send file
s.send(f.read())
elif response == 'no':
print "receiver doesn't want the file"
# cleanup
f.close()
s.close()
Empfänger:
from jmm_sockets import *
s = getServerSocket(None, 16001)
conn, addr = s.accept()
buffer = None
filename = str()
# receive filename
while 1:
buffer = conn.recv(1)
if buffer == '':
break
else:
filename = filename + buffer
print "sender wants to send", filename, "is that ok?"
user_choice = raw_input("ok/no: ")
if user_choice == 'ok':
# send ok
conn.send('ok')
#receive file
data = str()
while 1:
buffer = conn.recv(1)
if buffer=='':
break
else:
data = data + buffer
print data
else:
conn.send('no')
conn.close()
Ich bin sicher, bin ich etwas fehlt hier in der Art eines Deadlocks, aber nicht wissen, was es ist.
Lösung
TCP ist ein Streaming-Protokoll. Es hat kein Konzept von Nachrichtengrenzen. Für einen blockierenden Socket, recv (n) wird eine Rückkehr leere Zeichenfolge nur dann, wenn der Absender die Buchse oder explizit Abschaltung aufgerufen geschlossen (SHUT_WR). Andernfalls kann er eine Zeichenfolge aus einer Rückkehr zu n in der Länge Bytes und wird blockiert, bis es mindestens ein Byte zurückgeben muß.
Es ist an Ihnen, ein Protokoll zu entwerfen, um zu bestimmen, wenn Sie eine vollständige Nachricht haben. Einige Möglichkeiten sind:
- Verwenden Sie eine feste Länge Nachricht.
- Senden eine Nachricht mit fester Länge anzeigt, die Gesamtnachrichtenlänge, gefolgt von dem variablen Teil der Nachricht.
- Senden Sie die Nachricht, durch eine eindeutige Beendigungsnachricht gefolgt, die nie in der Nachricht auftreten.
Ein weiteres Problem kann man konfrontiert ist, dass senden ( ) nicht senden alle Daten garantiert. Der Rückgabewert gibt an, wie viele Bytes tatsächlich gesendet, und es liegt in der Verantwortung des Absenders mit der verbleibenden Nachricht Aufruf send zu halten Bytes, bis sie alle gesendet werden. Sie können vielmehr die Verwendung sendall () -Methode.
Andere Tipps
Mit blockierende Sockets, die Standardeinstellung sind und ich gehe davon sind, was Sie verwenden (kann nicht sicher sein, da Sie ein mysteriöses Modul jmm_sockets
verwenden), ist die recv
Methode blockiert - es wird kein leeres Rück Zeichenfolge, wenn es „nichts mehr für den Moment zurückzukehren“, wie Sie davon ausgehen, scheinen.
Sie könnten arbeiten, um diesen, zum Beispiel durch ein explizites Abschlusszeichen zu senden (das darf auf keinen Fall in einem Dateinamen auftreten), z.B. '\xff'
, nach der eigentlichen Zeichenfolge Sie senden möchten, und für sie am anderen Ende als Anzeige warten, dass alle die Zeichenfolge nun empfangen wurde.