2016-07-27 20 views
2

Ich habe einen neuen IRC-Client geschrieben, zu dem ich gerade den DCC-SEND-Teil hinzugefügt habe und daher die direkte Dateiübertragung für beide Benutzer der App unterstützt. Nichts, fancy, ich benutze die irc Python-Bibliothek, um den Client und Django für die GUI zu betreiben. Die große miniupnpc lib kümmert sich um die Portweiterleitung. Während die Datei ordnungsgemäß gesendet/empfangen wird, ist die Geschwindigkeit jedoch absolut HORREND: 20 KB/s ungefähr. Um den Server zu testen, habe ich ein Paket mit Hexchat gesendet: Die Upload-Geschwindigkeit war die maximale theoretische Bandbreite Geschwindigkeit (mit anderen Worten ausgezeichnet). Ich habe versucht, nach einem Puffer zu suchen, den ich vielleicht übersehen habe. Am Ende muss ich sagen, dass ich absolut keine Ahnung habe, warum meine Upload-Geschwindigkeit so schlecht ist und einen Einblick benötigt. Hier ist der relevante Teil meines Upload-Skripts.Python3; Geschwindigkeit beim Senden von Daten: IRC-Protokoll, DCC-Dateiübertragung

def on_dcc_connect(self, c, e): 
    t = threading.Timer(0, upload_monitoring, [self, c]) 
    t.start()  
    log("connection made with %s" % self.nickname).write() 
    self.file = open(self.filename, 'rb') 
    self.sendBlock() 


def sendBlock(self): 
    if self.position > 0: 
     self.file.seek(self.position) 
    block = self.file.read(1024) 
    if block: 
     self.dcc.send_bytes(block) 
     self.bytesSent = self.bytesSent + len(block) 
    else: 
     # Nothing more to send, transfer complete. 
     self.connection.quit() 

def on_dccsend(self, c, e): 
    if e.arguments[1].split(" ", 1)[0] == "RESUME": 
     self.position = int(e.arguments[1].split(" ")[3]) 
     c.ctcp("DCC", self.nickname, "ACCEPT %s %d %d" % (
     os.path.basename(self.filename), 
     self.eport, 
     self.position)) 



def on_dccmsg(self, connection, event): 
    data = event.arguments[0] 
    bytesAcknowledged = struct.unpack("!Q", data)[0] 
    if bytesAcknowledged < self.bytesSent: 
     return 
    elif bytesAcknowledged > self.bytesSent: 
     self.connection.quit() 
     return 
    self.sendBlock() 

send_bytes(block) Die Methode ist der Grund socket.send() Methode. Wenn ich den Puffer von file.read() vergrößern, erhalte ich den Fehler struct.pack, weil die Empfangsbestätigung des Clients (auch struct.pack) von meinem send-Skript nicht richtig gelesen wird: Daten nicht von Bytes Länge 8. Ist es das? file.read Puffer, der geändert werden muss? Wenn dies der Fall ist, warum ist die empfangene Byte-Bestätigung auf der Seite des Absenders nicht die selbe wie auf der Seite des Downloaders? Wenn nicht, wo sollte ich die Upload-Geschwindigkeit verbessern?

+1

Wir können nicht wirklich etwas darüber sagen, da wir keine Möglichkeit haben, die Leistung, die Sie sehen, zu reproduzieren. Meine Vermutung ist: Lesen einer Datei in 1KB Chunks und das Senden der Chunks als 1KB Pakete wird offensichtlich zu einer sehr niedrigen Leistung führen. Zumindest könnte die Datei in Blöcken von 64/128/512 KB gelesen werden und versuchen, die Größe der Pakete, die Sie im Netzwerk senden, so viel wie möglich zu erhöhen. – Bakuriu

+0

Hätten Sie in diesem Fall eine Idee, warum das bytesAcknowledged nicht mit dem vom Client gesendeten acknoldgement übereinstimmt? Es ist nur 'strukturiert = struct.pack ("! Q ", self.dict [bot] [" received_bytes "])' und dann 'connection.send_bytes (strukturiert)' – mrj

+0

Ich verstehe nicht, was Sie mich fragen. Beachten Sie, dass es beim Senden von Daten über Sockets passieren kann, dass * der Kernel * entscheidet, die Nachricht in mehr Pakete zu teilen, dies führt dazu, dass der Client weniger Daten liest. Es liegt in Ihrer Verantwortung, mehrere Anrufe zu führen, bis Sie alle Daten erhalten haben, die Sie benötigen. – Bakuriu

Antwort

0

Wie ich schon vermutet habe und wie Bakuriu darauf hingewiesen hat, lag das Problem tatsächlich an der file.read(buffer) Linie. Ich fand schließlich heraus, warum ich struct.pack Fehler hatte: die Bytes Bestätigung wurde ordnungsgemäß zurück an den Absender gesendet, aber manchmal wurden ein paar Pakete zusammengefügt. Das heißt, für jedes empfangene Paket wird eine Bestätigung an den Absender in Form einer gepackten, vorzeichenlosen Ganzzahl mit einer Länge von 8 Bytes beantwortet. Manchmal liest sock.recv() die eingehenden Daten nicht schnell genug und dann habe ich anstelle eines Bytes-Objekts der Länge 8 ein Byte-Objekt der Länge 16, 24, 32, 40 oder mehr. Deshalb konnte ich nicht einfach mit struct.pack("!Q", data) auspacken. Einmal hatte ich das herausgefunden, war die Lösung recht einfach zu finden:

def on_dccmsg(self, connection, event): 
    data = event.arguments[0][-8:] 
    bytesAcknowledged = struct.unpack("!Q", data)[0] 

Ich habe gerade gelesen, das letzte 8 Bytes aus den von sock.recv() gelesenen Daten anstatt alles zu lesen. Jetzt funktioniert es wie ein Zauber und die Upload-Geschwindigkeit ist die maximale theoretische Upload-Geschwindigkeit von meiner Bandbreite erlaubt !!!