制作一个'字节类型的对象'在python 3中

时间:2018-05-17 01:36:43

标签: python python-3.x networking python-3.6

我目前有一个在此代码下运行的服务器:

    import socket                   


port = 60000                  
s = socket.socket()             
host = socket.gethostname()    
s.bind((host, port))           
s.listen(1)                     

print ('Server listening....')

while True:
    conn, addr = s.accept()     
    print ('Got connection from', addr)
    data = conn.recv(1024)
    print('Server received', repr(data))

    filename='mytext.txt'
    f = open(filename,'rb')
    l = f.read(1024)
    while (l):
       conn.send(l)
       print('Sent ',repr(l))
       l = f.read(1024)
    f.close()

    print('Done sending')
    conn.send('Thank you for connecting')
    conn.close()

在此代码下运行的客户端:

import socket

    s = socket.socket()              
host = socket.gethostname()      
port = 60000                    

    s.connect((host, port)) 
    s.send('Test')

with open('received_file', 'wb') as f:
    print ('file opened')
    while True:
        print('receiving data...')
        data = s.recv(1024)
        print('data=%s', (data))
        if not data:
            break
        # write data to a file
        f.write(data)

    f.close() 
print('Successfully get the file') 
s.close()

     print('connection closed')

问题在于,当客户端尝试发送数据时,它表示发送的数据必须是字节类型的对象(此处显示错误代码:https://gyazo.com/97ef155f6809a801b02f381670895a2b。)我在互联网上搜索了答案如何在Python 3中创建一个字节类型对象,但我找不到任何有用的东西。

2 个答案:

答案 0 :(得分:2)

如果您只是发送文字,则可以使用bytes文字而不是str字面值,前缀为b。而不是:

sock.send('Hello')

......就这样做:

sock.send(b'Hello')

如果您要发送字符串变量,则需要encode发送字符串变量,并在接收时可能decode。而不是:

sock.send(msg)
resp = sock.recv(4096)

......做:

sock.send(msg.encode('ascii')
resp = sock.recv(4096).decode('ascii')

如果要发送非ASCII字符串,则需要选择编码。除非你有充分的理由不这样做,否则请使用UTF-8。

要记住的另一件事是:TCP套接字只是字节流,而不是消息,它们可以任意拆分成数据包。如果可以recv(1024),则可能只会获得对方通过send发送的内容的一部分。如果您发送的字符串长度超过1024字节,那可能很明显,但即使是较短的字符串,也可能发生。或者,如果您没有严格交替发送和接收,您可以将多个发送连接到单个接收。如果您发送hello然后world并将其作为helloworld接收,则无法知道发生了什么,或者如何将其拆分回来。

而且,更糟糕的是,当您在闲置计算机上测试localhost时,它可能不会发生,因此在开发过程中看起来会很好看,但是一旦你在整个地方都会神秘地失败把它部署到某个地方。

因此,您需要一些描述一条消息结束而另一条消息开始的协议。我有a blog post解释了一些选项,并展示了如何实现它们。

但是,如果您只是将人类可读的字符串作为消息发送,并且这些字符串永远不会包含换行符,则最简单的协议只是每条消息的一行,就像您编写文本文件一样。并查看socket.makefile:它为您提供的内容就像文件一样,为每个消息协议处理一行,并自动处理encodedecode部分。所以,而不是:

sock.send(msg.encode('utf-8'))
resp = sock.recv(1024).decode('utf-8')

...您只需使用makefile来获取可读写的文件对象,然后执行:

wf.write(msg + '\n')
resp = next(rf)

...然后您不必担心如何缓冲接收并将其拆分为消息。

答案 1 :(得分:1)

更改客户端代码行:

s.send('Test')

为:

s.send(b'Test')

https://docs.python.org/3/library/socket.html找到有关socket.send()的更多详细信息。