Python 3のソケットプログラムでType Errorに遭遇しました.'str'does not support the buffer interfaceの解決方法


回転:http://blog.csdn.net/chuanchuan608/article/details/17915959
今はpythonを勉強しています.使う道具はpython 3.2.3です.3 xバージョンと2 xバージョンの違いを発見しました.ソケットのプログラミングの時、長い間困っていました.まずpythonコアプログラミング書の例を紹介します.
コードは以下の通りです
サーバ端:
    # Echo server program  

    from socket import *  

    from time import ctime  

      

    HOST = ''                 # Symbolic name meaning all available interfaces  

    PORT = 50007              # Arbitrary non-privileged port  

    BUFSIZE = 1024  

    ADDR = (HOST, PORT)  

      

    tcpSerSock = socket(AF_INET, SOCK_STREAM)  

    tcpSerSock.bind(ADDR)  

    tcpSerSock.listen(5)  

      

    while True:  

        print('waiting for connection...')  

        tcpCliSock, addr = tcpSerSock.accept()  

        print('...connected from:', addr)  

      

        while True:  

            data = tcpCliSock.recv(BUFSIZE)  

            if not data:  

                break  

            tcpCliSock.send(('[%s] %s' % (ctime(), data)))  

      

            tcpCliSock.close()  

    tcpSerSock.close()  
 
クライアント
    # Echo client program  

    from socket import*  

      

    HOST = '127.0.0.1'  

    PORT = 50007              # The same port as used by the server  

    BUFSIZE = 1024  

    ADDR = (HOST, PORT)  

      

    tcpCliSock = socket(AF_INET, SOCK_STREAM)  

    tcpCliSock.connect(ADDR)  

    while True:  

        data = input('> ')  

        if not data:  

            break  

        tcpCliSock.send(data)  

        data = tcpCliSock.recv(BUFSIZE)  

        if not data:  

            break  

        print(data)  

          

    tcpCliSock.close()  
 
 
エラー:
   TypeError:'str'does not support the buffer interface
問題を探して長い間探しましたが、StockOverflowで同じ問題がある人を見つけました.Schronという人が答えを出しました.
In python 3、bytes strigs and unicode strings are now two different types.Since sockets are not aware of string encodings、they are using raw bytes stings、that have a slightly differentince from.
So,now,whenever you have a unicode stingthat you need to use as a byte string,you need toencode() it.And whenyou have a byte string,you need to decode it to use it as a reglar(python 2.x)string.
Unicode strigs ares enclosed stregs.Bytes strigs are b「」 enclosed streings
 
When you use clientsockett.send(data)、replace it by clientsockete.send(data.encode).When you get datausing data=client_sockett.recv(512)、replace it by data=client_sockett.recv(512).decode()
 
同時に私はpythonヘルプ文書を見ました.
Codec.encode(input[,errors])
Encodes the object input and returns apartuple.Ength consumed.Encoding converts a string object to abrytes using a particular character set encoding
 
Codec.decode(input[,errors])
Decodes the object input and returns apple.Decoding converts a bytes oject encoded using a particular set encoding to a string object.
input must be a bytes oject or one whichprovides the read-only character buffer interface–for example,buffer oject said memory mapped files.
 
ソケットのメンバー関数send
socket.send(bytes[,flags])はバイトタイプとして登録されています.
sockett.recv(bufsize[,flags])Receive datafrom the socket.The return value is abytes object representing the data received.
 修正後のコードは以下の通りです.
サーバ端:
   # Echo server program  

    from socket import *  

    from time import ctime  

      

    HOST = ''                 # Symbolic name meaning all available interfaces  

    PORT = 50007              # Arbitrary non-privileged port  

    BUFSIZE = 1024  

    ADDR = (HOST, PORT)  

      

    tcpSerSock = socket(AF_INET, SOCK_STREAM)  

    tcpSerSock.bind(ADDR)  

    tcpSerSock.listen(5)  

      

    while True:  

        print('waiting for connection...')  

        tcpCliSock, addr = tcpSerSock.accept()  

        print('...connected from:', addr)  

      

        while True:  

            data = tcpCliSock.recv(BUFSIZE).decode()  

            if not data:  

                break  

            tcpCliSock.send(('[%s] %s' % (ctime(), data)).encode())  

      

            tcpCliSock.close()  

    tcpSerSock.close()  
 
 
サービス:
# Echo client program  

from socket import*  

  

HOST = '127.0.0.1'  

PORT = 50007              # The same port as used by the server  

BUFSIZE = 1024  

ADDR = (HOST, PORT)  

  

tcpCliSock = socket(AF_INET, SOCK_STREAM)  

tcpCliSock.connect(ADDR)  

while True:  

    data = input('> ')  

    if not data:  

        break  

    tcpCliSock.send(data.encode())  

    data = tcpCliSock.recv(BUFSIZE).decode()  

    if not data:  

        break  

    print(data)  

      

tcpCliSock.close() 
 
 
運転結果:予想通り
これらの関数を使う時はもちろん使いたいです.ヘルプドキュメントを探していません.タイプがよく分かりません.例の問題かもしれません.これらに注意していませんが、教訓をくみ取ります.
同じudpの場合:修正しました.
サーバ端:
    from socket import *  

    from time import ctime  

      

    HOST = '';  

    PORT = 21546  

    BUFSIZE = 1024  

    ADDR = (HOST, PORT)  

      

    udpSerSock = socket(AF_INET, SOCK_DGRAM)  

    udpSerSock.bind(ADDR)  

      

    while True:  

        print('waiting for message...')  

        data, addr = udpSerSock.recvfrom(BUFSIZE)  

        udpSerSock.sendto(('[%s] %s' %(ctime(), data.decode())).encode(), addr)  

        print('...received from and returned to:', addr)  

      

    udpSerSock.close()  
 
クライアント:
    from socket import *  

      

    HOST = 'localhost'  

    PORT = 21567  

    BUFSIZE = 1024  

    ADDR = (HOST, PORT)  

      

    while True:  

        tcpCliSock = socket(AF_INET, SOCK_STREAM)  

        tcpCliSock.connect(ADDR)  

        data = input('> ')  

        if not data:  

            break  

        tcpCliSock.send(('%s\r
' % data).encode()) data = tcpCliSock.recv(BUFSIZE).decode() if not data: break print(data.strip()) tcpCliSock.close()
 
 
socketserverモジュールを使う:
サーバ端:
    #TsTservss.py  

    from socketserver import TCPServer as TCP, StreamRequestHandler as SRH  

    from time import ctime  

      

      

    HOST = ''  

    PORT = 21567  

    ADDR = (HOST, PORT)  

      

    class MyRequestHandler(SRH):  

        def handle(self):  

            print('...connected from:', self.client_address)  

            self.wfile.write(('[%s] %s' %(ctime(), self.rfile.readline().decode())).encode())  

      

    tcpServ = TCP(ADDR, MyRequestHandler)  

    print('waiting for connection...')  

    tcpServ.serve_forever()  
 
クライアント:
    from socket import *  

      

    HOST = 'localhost'  

    PORT = 21567  

    BUFSIZE = 1024  

    ADDR = (HOST, PORT)  

      

    while True:  

        tcpCliSock = socket(AF_INET, SOCK_STREAM)  

        tcpCliSock.connect(ADDR)  

        data = input('> ')  

        if not data:  

            break  

        tcpCliSock.send(('%s\r
' % data).encode()) data = tcpCliSock.recv(BUFSIZE).decode() if not data: break print(data.strip()) tcpCliSock.close()