2017-01-10 18 views
1

我正在用Python編寫在線多人遊戲控制檯遊戲。服務器使用Python 3.0,客戶端使用Python 2.7(因爲我想用我的智能手機,我只能找到它的Python 2.7)。但是,我無法在服務器和客戶端之間轉換字符串的編碼。如何在Python 3.0上編碼字符串並通過套接字在Python 2.7上正確解碼

我寫了兩個函數,sendDatareceiveData發送和接收來自套接字連接的字符串。問題是,當我通過在服務器端「UTF-8」編碼字符串你好,並在客戶端進行解碼,我得到了客戶這個錯誤:

UnicodeDecodeError: 'utf8' codec can't decode bytes in position 0-1: unexpected end of data

我就用盡全力兩側encode('utf-8')decode*('utf-8')雙方,但都沒有工作。我也嘗試使用泡菜,但得到這個錯誤在客戶端上:

ValueError: unsupported pickle protocol: 3

那麼我應該如何編碼和解碼字符串?

這裏是我的服務器代碼(Python的3.0,datatrans.py):

def sendData(sock, data): 
    ''' 
    Send string through socket. 
    ''' 
    sock.send(struct.pack('Q', len(data))) 
    sock.send(bytes(data.encode('utf-8'))) # This might be the cause of the error 

def receiveData(sock): 
    ''' 
    Receive object from socket. 
    ''' 
    lengthLeft = struct.unpack('Q', sock.recv(struct.calcsize('Q')))[0] 
    data = bytes() 
    while lengthLeft > 0: 
     block = sock.recv(lengthLeft) 
     data += block 
     lengthLeft -= len(block) 
    return str(data) 

服務器的主腳本(Python的3.0):

import socket 
import threading 
import socket 
from datatrans import sendData, receiveData 
import time 

port = int(input('Listen on port:')) 

def log(string): 
    return '[%s]%s' % (str(time), string) 

def handleRequest(sock): 
    sendData(sock, '你好') 

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.bind(('0.0.0.0', port)) 
s.listen(5) 

try: 
    while True: 
     sock, addr = s.accept() 
     print(log('%s entered the game' % str(addr))) 
     #print sock.recv(1000) 
     threading.Thread(target = handleRequest, args = (sock,)).start() 
finally: 
    s.close() 

我的客戶端代碼是這樣的,與sendDatareceiveData變化不大(Python 2.7版):

# -*- coding: UTF-8 -*- 
import socket 
import struct 

def sendData(sock, data): 
    ''' 
    Send string through socket. 
    ''' 
    sock.send(struct.pack('Q', len(data))) 
    sock.send(data) 

def receiveData(sock): 
    ''' 
    Receive object from socket. 
    ''' 
    lengthLeft = struct.unpack('Q', sock.recv(struct.calcsize('Q')))[0] 
    data = '' 
    while lengthLeft > 0: 
     block = sock.recv(lengthLeft) 
     data += block 
     lengthLeft -= len(block) 
    return data.decode('utf-8') # Error comes from here 

while True: 
    try: 
     ip = raw_input('Sever IP:') 
     port = int(raw_input('Port:')) 

     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     s.connect((ip, port)) 
    except socket.error as error: 
     print('Error while connecting') 
     print(error) 
     print('') 
    else: 
     break 

while True: 
    print(receiveData(s)) 

另外,我想知道WH在發送一個由用戶從客戶端輸入到服務器的字符串時應該怎麼做,以便服務器不會抱怨編碼錯誤? Python 2.7在不同的系統上使用不同的編碼,所以我現在不知道如何處理它。謝謝!

回答

0

你有一個問題,你的Python2程序dealingwith字節串所有的時間(也就是 - 不是Unicode字符串),但你嘗試解碼你在哪裏得到錯誤的有效載荷。

如果這是一個小的應用程序,也許只是跳過解碼步驟和程序的客戶端應用程序來處理UTF-8編碼的字節strigns所有的時間。 (但是如果你不得不通過獲取輸入並通過網絡發送文本來處理文本,那麼這是不可行的。

現在,這不是您向我們展示的UnidodeDecode錯誤的來源 - 既然服務器正確地編碼了數據,並且即使它是雙重編碼,也不會發生此特定錯誤。

會發生什麼事是,在服務器端你計算的文本字符串的lenght - 預編碼,並把它們它編碼爲UTF-8。在你的例子中,我們向你展示的這類字符,utf-8每個字符最多佔用4個字節。

所以,你犯了一個有效載荷宣佈你有lenght「2」的字符串,並將其傳輸8個字節 - 和文本解碼器將需要其中4個實際轉變角色了。

就改寫這個:

def sendData(sock, data): 
    ''' 
    Send string through socket. 
    ''' 
    sock.send(struct.pack('Q', len(data))) 
    sock.send(bytes(data.encode('utf-8'))) 

要這樣:

def sendData(sock, data): 
    ''' 
    Send string through socket. 
    ''' 
    encoded_data = data.encode('utf-8') 
    sock.send(struct.pack('Q', len(encoded_data))) 
    sock.send(bytes(encoded_data)) 

你應該消除這種主要的錯誤。

此外,在服務器現場接收功能TE最後一行不可能是: return str(data) - 使其return data.decode('utf-8')代替。