TypeError: Can't convert 'bytes' object to str implicitly while working with sockets

TypeError: Can't convert 'bytes' object to str implicitly while working with sockets

所以我正在尝试将代码从 Python 2.7 转换为 Python 3,似乎有些东西发生了变化。我试图通过套接字接收二进制数据,但现在它不起作用。这是我的代码。

编辑:我添加了我的发送代码。另外,我真的不喜欢它现在的工作方式,它太复杂了。如果可以的话,最好有一种更好的 sending/receiving 数据方式。

def recv(self):
    # Receive the length of the incoming message (unpack the binary data)
    dataLength = socket.ntohl(struct.unpack("I", self._recv(4))[0])

    # Receive the actual data
    return self._recv(dataLength)

def _recv(self, length):
    try:
        data = ''
        recvLen = 0
        while recvLen < length:
            newData = self.sock.recv(length-recvLen)

            if newData == '':
                self.isConnected = False
                raise exceptions.NetworkError(errors.CLOSE_CONNECTION, errno=errors.ERR_CLOSED_CONNECTION)

            data = data + newData # TypeError here
            recvLen += len(newData)

        return data
    except socket.error as se:
        raise exceptions.NetworkError(str(se))

def send(self, data):
    if type(data) is not str:
        raise TypeError()

    dataLength = len(data)

    # Send the length of the message (int converted to network byte order and packed as binary data)
    self._send(struct.pack("I", socket.htonl(dataLength)), 4)

    # Send the actual data
    self._send(data, dataLength)

def _send(self, data, length):
    sentLen = 0
    while sentLen < length:
        try:
            amountSent = self.sock.send(data[sentLen:])
        except Exception:
            self.isConnected = False
            raise exceptions.NetworkError(errors.UNEXPECTED_CLOSE_CONNECTION)

        if amountSent == 0:
            self.isConnected = False
            raise exceptions.NetworkError(errors.UNEXPECTED_CLOSE_CONNECTION)

        sentLen += amountSent

Python 3 以字节形式发送数据,因此您必须解码为字符串

 data = data + newData.decode('utf-8')

 # or 

 data = data + newData.decode('ascii')

如果您需要字节数据,请使用

 data = b''

并保留 .decode()

 data = data + newData

编辑: 有问题的新代码。

当你发送时,你必须 convert/encode 字符串到字节,然后得到它的长度。本机字符的 unicode 长度为 1,但它们可以使用 2 个字节(或更多)。

当您收到时,您必须使用字节 b'' 并在最后 convert/decode 字节再次转换为字符串。

请参阅代码

中的注释 # <--
def send(self, data):
    if not isinstance(data, str): # <-- prefered method
    #if type(data) is not str:
        raise TypeError()

    data = data.encode('utf-8') # <-- convert to bytes

    # get size of bytes
    dataLength = len(data)

    # Send the length of the message (int converted to network byte order and packed as binary data)
    self._send(struct.pack("I", socket.htonl(dataLength)), 4)

    # Send the actual data
    self._send(data, dataLength)


def recv(self):
    # Receive the length of the incoming message (unpack the binary data)
    dataLength = socket.ntohl(struct.unpack("I", self._recv(4))[0])

    # Receive the actual data
    return self._recv(dataLength).decode('utf-8') # <-- convert to string again

def _recv(self, length):
    try:
        data = b'' # <-- use bytes
        recvLen = 0
        while recvLen < length:
            newData = self.sock.recv(length-recvLen)

            #if newData == b'': # <-- use bytes
            if not newData:    # <-- or 
                self.isConnected = False
                raise exceptions.NetworkError(errors.CLOSE_CONNECTION, errno=errors.ERR_CLOSED_CONNECTION)

            data = data + newData # TypeError here
            recvLen += len(newData)

        return data
    except socket.error as se:
        raise exceptions.NetworkError(str(se))