2013-03-29 54 views
0

我做了2个应用程序: 客户端从sql server(10k行)提取数据,并通过套接字将每一行pickle发送到“收集器”服务器。 服务器使用扭曲(这是强制性的)并接收每一行,解开它并将数据存储在另一个sql服务器中。泡菜是否与扭曲不兼容?

每次我做起,从客户端发送数据到服务器,在第200行(每次不同的线路)服务器抛出异常: 有时是这样的:

Traceback (most recent call last): 
    File "collector2.py", line 81, in dataReceived 
    self.count,account = pickle.loads(data) 
    File "/usr/lib/python2.6/pickle.py", line 1374, in loads 
    return Unpickler(file).load() 
    File "/usr/lib/python2.6/pickle.py", line 858, in load 
    dispatch[key](self) 
    File "/usr/lib/python2.6/pickle.py", line 1138, in load_pop 
    del self.stack[-1] 
IndexError: list assignment index out of range 

,但它不是每时间一样。打印我的例外,我红: 例外:从空列表 异常弹出:列表索引超出范围 例外的:“'” 异常:列表分配索引超出范围

另一个奇怪的错误是: 文件“/ USR /lib/python2.6/pickle.py”,线路1124,在find_class 进口(模块) exceptions.ImportError:没有

for i in listaSAI: 
    crm={} 
    try: 
     crm['uid']=i[0] 
    except: 
     crm['uid']=None 
    try: 
     crm['type_cond']=i[01] 
    except: 
     crm['type_cond']=None 
    try: 
     crm['population_id']=i[2] 
    except: 
     crm['population_id']=None 
    try: 
     crm['product_id']=i[3] 
    except: 
     crm['product_id']=None 
    try: 
     crm['a_id']=i[4] 
    except: 
     crm['a_id']=None 
    try: 
     crm['status']=i[5] 
    except: 
     crm['status']=None 
    #time.sleep(0.001) 
    serialized = pickle.dumps((count,crm)) 
    #print "sent num", count, crm 
    s.sendall(serialized) 
    count += 1 

模块名为OND”我的服务器:

def dataReceived(self, data): 
    try: 
     self.count,account = pickle.loads(data)   
    except Exception as e: 
     print "Eccezione:", e 
     print self.count+1 
     print "DISAGIO", data 
     print traceback.print_exc() 

在我的客户端打印数据告诉我一切正常。 如果我试图减慢使用time.sleep(0.01)在我的客户端发送的过程,一切都很好,并且不会引发异常。

我能做些什么来调试我的代码?

p.s. 我怀疑exceptions.ImportError:没有名为ond的模块引用crm中的“type_cond”键。

回答

1

由于在写入之间添加延迟时没有问题,因此很明显,问题与pickle无关,而与数据的传输无关。

一种选择是客户端一直写入数据的速度比服务器能处理它快,导致缓冲区溢出和数据包丢失。

或者,您是否有多个线程可能同时写入套接字?

1

你的协议没有成帧,你试图使用SOCK_STREAM(TCP连接),就好像它是面向数据报的(即,像SOCK_DGRAM,就像UDP一样)。

因此,你发送一些字节组成一个完整的pickled数据集,但服务器不知道特定的pickle数据集开始或结束的位置。相反,接收代码会尝试解除随机发送的任何字节块。

正如您发现的那样,有时会起作用。但是,不能保证您传递给sock.sendall的字节将作为单个组传送到dataReceived。您必须添加帧,以便接收器可以发现消息边界。这有几种方法。一种方法是添加长度前缀。然后接收器知道要等待多少个字节,并且可以在接收到正确的数字时取消它们。

当然,您永远不应该通过网络取消接收的数据。请参阅http://docs.python.org/2/library/pickle.html上的大红色框?它就在那里,因为如果您编写的服务器类似于您在此处展示的服务器,那么您已经编写了一个远程任意代码漏洞的服务器,其大小足以驱动半透明。

由于您的数据看起来相当简单和结构化,我建议您改为参考AMP