当pickle时,socket中的TypeError

时间:2014-05-10 19:35:06

标签: python multithreading sockets pickle

我正在尝试编写一个客户端 - 服务器程序,其中服务器接收对数据库记录或文件的请求,然后将其发回。一切都工作得很好,直到我使用pickle函数从客户端发送数据到服务器,

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner
    self.run()
  File "server.py", line 71, in run
    data = pickle.loads(data)
  File "/usr/lib/python2.7/pickle.py", line 1381, in loads
    file = StringIO(str)
TypeError: expected read buffer, NoneType found

当我从服务器向客户端发送数据时,没有问题。我这样工作了几个星期但是当有大约50个例外时,服务器程序关闭了。

client.py文件:

import socket
import sys
import time
import pickle
import struct
def recvall(sock, n):
    # Helper function to recv n bytes or return None if EOF is hit
    data = ''
    while len(data) < n:
        packet = sock.recv(n - len(data))
        if not packet:
            return None
        data += packet
    return data

def recv_msg(sock):
    # Read message length and unpack it into an integer
    raw_msglen = recvall(sock, 4)
    if not raw_msglen:
        return None
    msglen = struct.unpack('>I', raw_msglen)[0]
    # Read the message data
    return recvall(sock, msglen)


def sending(msg):
    host = 'localhost'
    port = 50000
    size = 1024
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((host,port))
    lenght = len(msg)
    if lenght>0:
        msg = pickle.dumps(msg)
        msg = struct.pack('>I', len(msg)) + msg
        s.sendall(msg)
        print 'sended string lenght: '+str(lenght)
    else:
        s.send('nothing sended')
    data = recv_msg(s)
    lenght2 = len(data)
    print data
    print 'received string lenght: '+str(lenght2)
    #sys.stdout.write(data)
    s.close()

while 1:
    msg = raw_input('Input:')
    sending(msg)

server.py:

class Client(threading.Thread): 
    def __init__(self,(client,address)): 
        threading.Thread.__init__(self) 
        self.client = client 
        self.address = address 
        self.size = 1024 

    def run(self): 
        running = 1 
        while running: 
            sock = self.client
            data = self.recv_msg(sock)
            data = pickle.loads(data)
            if data:
                msg = struct.pack('>I', len(data)) + data
                self.client.sendall(msg)
            else: 
                self.client.close() 
                running = 0 

    def recv_msg(self, sock):
        # Read message length and unpack it into an integer
        raw_msglen = self.recvall(sock, 4)
        if not raw_msglen:
            return None
        msglen = struct.unpack('>I', raw_msglen)[0]
        # Read the message data
        return self.recvall(sock, msglen)

    def recvall(self, sock, n):
        # Helper function to recv n bytes or return None if EOF is hit
        data = ''
        while len(data) < n:
            packet = sock.recv(n - len(data))
            if not packet:
                return None
            data += packet
        return data 

在之前的版本中,我将pickle功能从服务器发送到客户端,它工作正常,没有任何问题,但现在我开始从头开始编写它以找到问题,但我没有。 在这里找到了recv_msg方法: Python Socket Receive Large Amount of Data

1 个答案:

答案 0 :(得分:1)

当达到EOF时,recv_msg方法会返回None,并且您将None传递给pickle.loads,这是一个错误。

要解决此问题,请在 EOF检查后拨打pickle.loads()

        data = self.recv_msg(sock)
        if data is not None:
            data = pickle.loads(data)
            msg = struct.pack('>I', len(data)) + data
            self.client.sendall(msg)
        else: 
            self.client.close() 
            running = 0