2016-11-17 103 views
0

我試圖做一個JavaScript客戶端和python服務器之間的網絡套接字連接。我已經成功地握手了,我可以從JavaScript客戶端發送數據,並在服務器上解碼。Python編碼網絡套接字框架

當我想從服務器發送數據時出現問題。當我嘗試發送明確的ASCII文本時,我在客戶端Websocket Error: [object Event]上收到此錯誤。自然,所以我想在發送數據之前對數據進行「編碼」。我嘗試了很多東西,包括基本的base64。但沒有任何工作。我偶然發現了這個thread。它是一個如何準備發送數據的例子。

下面是代碼我想出了迄今:

def encodeFrame(bytesRaw): 
bytesFormatted = [] 
bytesFormatted.append(129) 

indexStartRawData = 0 

if len(bytesRaw) <= 125: 
    bytesFormatted.append(len(bytesRaw)) 

    indexStartRawData = 2 

elif len(bytesRaw) >= 126 and len(bytesRaw) <= 65535: 
    bytesFormatted.append(126) 
    bytesFormatted.append((len(bytesRaw) >> 8) + 255) 
    bytesFormatted.append((len(bytesRaw)) + 255) 

    indexStartRawData = 4 

else: 
    bytesFormatted.append(127) 
    bytesFormatted.append((len(bytesRaw) >> 56) + 255) 
    bytesFormatted.append((len(bytesRaw) >> 48) + 255) 
    bytesFormatted.append((len(bytesRaw) >> 40) + 255) 
    bytesFormatted.append((len(bytesRaw) >> 32) + 255) 
    bytesFormatted.append((len(bytesRaw) >> 24) + 255) 
    bytesFormatted.append((len(bytesRaw) >> 16) + 255) 
    bytesFormatted.append((len(bytesRaw) >> 8) + 255) 
    bytesFormatted.append((len(bytesRaw)) + 255) 

    indexStartRawData = 10 

bytesFormatted.put(bytesRaw, indexStartRawData) 

return bytesFormatted 

我想大部分作品的權利,但我不知道我應該用最後的命令做:bytesFormatted.put(bytesRaw, indexStartRawData)。我試着追加到數組,並使用緩衝區格式。但它不會工作。發送數據的功能client.send(encodeFrame("test"))在我的情況下,只需要一個緩衝區或字符串。

有沒有人有任何想法如何做到這一點「編碼」?

回答

1

我沒有關注這些(len(bytesRaw) >> 32) + 255行。 舉例來說,如果你的有效載荷長度爲70'000,else子句就會執行,給你的

[127, 255, 255, 255, 255, 255, 256, 528, 70255] 

這是一個順序沒有多大意義的我。實際上,您提供的鏈接建議使用binary AND操作,而您使用算術+(如果要對二進制形式的非重疊1進行二進制或運算,則可以使用+,但對於進行AND操作不適用)。這些是非常不同的操作!

雖然您可能會使用(len(bytesRaw) >> 32) & 255它不能保證數字將是單個字節長 - 這取決於解釋器決定如何存儲它。爲了克服這個問題,Python中的struct模塊用於彙編二進制數據。例如,整個else子句收縮爲struct.pack('B', 127) + struct.pack('!Q', len(bytesRaw))!表示網絡字節順序(big-endian),Q表示8字節無符號整數,B表示無符號字節。

即使您不想用struct(我當然不堅持)重寫代碼,目前您從encodeFrame函數返回list。您無法通過網絡發送清單。你可以發送C數組,但Python列表是一個非常複雜的對象,不能以這種方式發送。你需要將其轉換爲一個字節序列第一:

def list_to_bytes(lst): 
    format = 'B' * len(lst) 
    return struct.pack(format, *lst) 

同時,請不要忘記,你的有效載荷應該是一個有效的UTF-8字符串,因爲你使用文本框。詳情請參閱RFC 6455

+0

謝謝,完美的作品! – jakobS