2016-07-27 98 views
2

我已經寫了一個新的IRC客戶端,我剛剛添加了DCC SEND部分,因此支持應用程序的兩個用戶的直接文件傳輸。沒有什麼,看上去,我正在使用irc python庫來爲GUI和Django供電。偉大的miniupnpc lib負責端口轉發。但是,在正確發送/接收文件時,速度絕對爲HORRENDOUS:大約20 KB/s。爲了測試服務器,我使用Hexchat發送了一個包:上傳速度是最大的理論帶寬速度(換句話說,非常好)。我試圖尋找某種我可能錯過的緩衝區。最後,我必須說我完全不知道爲什麼我的上傳速度太糟糕了,需要一些洞察力。這是我的上傳腳本的相關部分。Python3;發送數據時的速度:IRC協議,DCC文件傳輸

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)方法是基本的方法socket.send()。當我增加file.read()的緩衝區時,我得到struct.pack錯誤,因爲我的發送腳本沒有正確讀取客戶端的數據塊接收確認(也是struct.pack):字節長度爲8的數據不正確嗎?必須更改的file.read緩衝區?如果是這樣,爲什麼在發送方一側收到的字節不同於下載者的一方?如果不是,我應該在哪裏提高上傳速度?

+1

由於我們無法重現您所看到的效果,所以我們無法對此進行任何說明。我的猜測是:以1KB的塊讀取一個文件並將這些塊作爲1KB數據包發送,顯然會導致性能很低。至少該文件可以以64/128/512 KB的塊讀取,並嘗試儘可能地增加您在網絡上發送的數據包的大小。 – Bakuriu

+0

在這種情況下,你會有什麼想法,爲什麼字節acknowledgeged與客戶發送的acknoldgement不一樣?它只是'structured = struct.pack(「!Q」,self.dict [bot] [「received_bytes」]),然後是'connection.send_bytes(structured)' – mrj

+0

我不明白你在問我什麼。請注意,通過套接字發送數據時,可能發生*內核*決定將消息分成更多數據包,這會導致客戶端讀取的數據更少。在您收到您需要的所有數據之前,您有責任執行多次呼叫。 – Bakuriu

回答

0

正如我已經懷疑,Bakuriu指出,問題確實在於file.read(buffer)線。我終於找到了爲什麼我有struct.pack錯誤:字節確認已正確發送回發件人,但有時幾個數據包連接在一起。也就是說,對於接收到的每個數據包,以8字節長度的壓縮無符號整數的形式向發送方回答確認。有時候,sock.recv()不會以足夠快的速度讀取傳入數據,然後,而不是長度爲8的字節對象,我有一個長度爲16,24,32,40或更多的字節對象。這就是爲什麼我不能只用struct.pack("!Q", data)解包。有一次,我是想通了,該解決方案是很容易找到:

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

我剛纔讀通過sock.recv(),而不是閱讀所有讀取數據的最後8個字節。現在它就像一個魅力,上傳速度是我的帶寬允許的最大理論上傳速度!