Question

I'm trying to write a client-server program where server receives the requests for a database records, or files, and sends it back. Everything was working just fine until I used the pickle function to send data from client to server,

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

When I send data from server to client, there is no problem. I worked like this for a few weeks but when there is about 50 exceptions, the server program closes.

client.py file:

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 

In previous version I puted the pickle function from server to client, and it worked fine, no problems, but now I started to write it from the beginning to find the problem, but I didn't. The recv_msg method was found here: Python Socket Receive Large Amount of Data

Was it helpful?

Solution

The recv_msg method returns None when EOF is reached, and you pass that None to pickle.loads, which is an error.

To fix the problem, place the call to pickle.loads() after the EOF-check:

        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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top