• TCP客户端和服务器间传输数据遇到的TypeError: a bytes-like object is required, not 'str'问题


    使用python实现python核心编程3第472页和474页的TCP时间戳服务器和客户端服务器间数据传输编程时遇到TypeError: a bytes-like object is required, not 'str'报错问题,经查找资料知道是Python中的字符串数据和字节数据在python3中不能混用所致,一博文 https://eli.thegreenplace.net/2012/01/30/the-bytesstr-dichotomy-in-python-3 对python3中字符串和字节数据间区别联系做了较详细解释。

    下面是https://www.cnblogs.com/abclife/p/7445222.html 进行的译文

    python 3中最重要的新特性可能就是将文本(text)和二进制数据做了更清晰的区分。文本总是用unicode进行编码,以str类型表示;而二进制数据以bytes类型表示。

    在python3中,不能以任何隐式方式将str和bytes类型二者混合使用。不可以将str和bytes类型进行拼接,不能在str中搜索bytes数据(反之亦然),也不能将str作为参数传入需要bytes类型参数的函数(反之亦然)。

    字符串和字节符之间划分界线是必然的。下面这个图解要牢记于心:

    strings可以被编码(encode)成字bytes,bytes也可以解码(decode)成strings:

    1 >>> '€20'.encode('utf-8')
    2 b'xe2x82xac20'
    3 >>> b'xe2x82xac20'.decode('utf-8')
    4 '€20'

    可以这样理解:

    string是文本(text)的抽象表示。字符串(string)由字符组成,字符也是抽象的实体且与任何二进制表示无关。
    当操纵字符串的时候,很多细节是不用了解的。我们可以分割、切片和拼接字符串,在字符串内部进行搜索。但并不在乎内部是如何表示的,也不用在意底层一个字符要花费多少byte。
    只有在需要将string编码(encode)成byte的时候,比如:通过网络传输数据;或者需要将byte解码(decode)成string的时候,我们才会关注string和byte的区别。

    传入encode和decode的参数是编码方式。编码是一种用二进制数据表示抽象字符的方式。目前有很多种编码。上面给出的UTF-8是其中一种,下面是另一种:

    1 >>> '€20'.encode('iso-8859-15')
    2 b'xa420'
    3 >>> b'xa420'.decode('iso-8859-15')
    4 '€20'

    编码是这个转换过程中至关重要的一部分。若不编码,bytes对象b'xa420'只是一堆比特位而已。编码赋予其含义。采用不同的编码,这堆比特位的含义就会大不同:

    1 >>> b'xa420'.decode('windows-1255')
    2 '₪20'

    因而服务器端编码

     1 from socket import *
     2 from time import ctime
     3 
     4 HOST=''
     5 PORT=21567
     6 BUFSIZ=1024
     7 ADDR=(HOST,PORT)
     8 
     9 tcpSerSock=socket(AF_INET,SOCK_STREAM)
    10 tcpSerSock.bind(ADDR) #绑定地址到套接字
    11 tcpSerSock.listen(5) #开始TCP监听
    12 
    13 while True:
    14     print('waiting for connection...')
    15     tcpSerSock,addr=tcpSerSock.accept()#被动接受TCP客户端连接,等待连接的到来
    16     print('...connected from:',addr)
    17 
    18     while True:
    19         data=tcpSerSock.recv(BUFSIZ)
    20         print(data.decode())        #服务器接受到客户端发送来的数据是字节类型,需要转换为字符串类型
    21         if not data:
    22             break
    23         tcpSerSock.send(('[%s] %s'%(ctime(),data)).encode()) # 网络传输数据前将字符串数据转化为字节类型
    24     tcpSerSock.close()
    25 tcpSerSock.close()

    客户端编程

     1 from socket import *
     2 
     3 HOST='localhost'
     4 PORT=21567
     5 BUFSIZ=1024
     6 ADDR=(HOST,PORT)
     7 
     8 tcpCliSock=socket(AF_INET,SOCK_STREAM)
     9 tcpCliSock.connect(ADDR)
    10 
    11 while True:
    12     data=input('>')
    13     if not data:
    14         break
    15     tcpCliSock.send(data.encode()) #网络传输数据前将字符串数据转化为字节类型
    16     data=tcpCliSock.recv(BUFSIZ).decode() #将收到的字节类型数据转化为字符串数据
    17     if not data:
    18         break
    19     print(data)
    20 
    21 
    22 tcpCliSock.close()

    客户端显示

    1 >what??
    2 [Sat Mar 31 16:03:20 2018] b'what??'
    3 >excuse me?
    4 [Sat Mar 31 16:03:52 2018] b'excuse me?'
    5 >

    服务器端显示

    1 waiting for connection...
    2 ...connected from: ('127.0.0.1', 50782)
    3 what??
    4 excuse me?

    udp服务器端编程

     1 from socket import *
     2 from time import ctime
     3 
     4 HOST=''
     5 PORT=21567
     6 BUFSIZ=1024
     7 ADDR=(HOST,PORT)
     8 
     9 udpSerSock=socket(AF_INET,SOCK_DGRAM)
    10 udpSerSock.bind(ADDR)
    11 
    12 while True:
    13     print('waiting for message...')
    14     data,addr=udpSerSock.recvfrom(BUFSIZ) #data是字节对象,addr是字符串对象
    15     print(data)
    16     print(addr)
    17     data=data.decode()
    18     data='[%s]%s'%(ctime(),data)
    19     udpSerSock.sendto(data.encode(),addr)
    20     print('..received from and returned to:',addr)
    21 
    22 udpSerSock.close()

    客户端编程

     1 from socket import *
     2 
     3 HOST='localhost'
     4 PORT=21567
     5 BUFSIZ=1024
     6 ADDR=(HOST,PORT)
     7 
     8 udpCliSock=socket(AF_INET,SOCK_DGRAM)
     9 while True:
    10     data=input('>').encode()
    11     if not data:
    12         break
    13     udpCliSock.sendto(data,ADDR)
    14     data,ADDR=udpCliSock.recvfrom(BUFSIZ)
    15     if not data:
    16         break
    17     else:
    18         print(data.decode())
    19     # print(udpCliSock.close())
    20 
    21 udpCliSock.close()

    服务器端显示

     1 waiting for message...
     2 b'who is that?'
     3 ('127.0.0.1', 60959)
     4 ..received from and returned to: ('127.0.0.1', 60959)
     5 waiting for message...
     6 b'I am Jack'
     7 ('127.0.0.1', 60959)
     8 ..received from and returned to: ('127.0.0.1', 60959)
     9 waiting for message...
    10 b'sending through UDP'
    11 ('127.0.0.1', 60959)
    12 ..received from and returned to: ('127.0.0.1', 60959)
    13 waiting for message...

    客户端显示

    1 >who is that?
    2 [Sat Mar 31 16:47:15 2018]who is that?
    3 >I am Jack
    4 [Sat Mar 31 16:47:24 2018]I am Jack
    5 >sending through UDP
    6 [Sat Mar 31 16:47:32 2018]sending through UDP
    7 >
  • 相关阅读:
    golang 数组的一些自问自答
    这辈子研究 我的闪存
    我写的诗 爱你等于爱自己
    个人创业相关资料 创业与投资文章
    公司商业模式案例讲座 公司商业模式
    1、开篇:公司的价值 企业管理线细化系列文章
    visual studio 2022 企业版 下载
    芝奇DDR4 5066Hz 8Gx2内存闲置 个人闲置物品买卖
    INF: How SQL Server Compares Strings with Trailing Spaces
    虚拟 DOM 到底是什么?
  • 原文地址:https://www.cnblogs.com/xiongxueqi/p/8682685.html
Copyright © 2020-2023  润新知