0

我做了 2 个应用程序:客户端从 sql 服务器(10k 行)中提取数据,并通过套接字将腌制的每一行发送到“收集器”服务器。服务器使用twisted(这是强制性的)并接收每一行,将其解压并将数据存储在另一个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 导入(模块)异常中。ImportError: No module named ond'

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

还有我的服务器:

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) 减慢发送过程,一切都很好,并且不会引发异常。

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

ps 我怀疑 exceptions.ImportError: No module named ond' 指的是 crm 中的“type_cond”键。

4

2 回答 2

1

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

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

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

于 2013-03-29T05:47:09.650 回答
1

您的协议没有框架,并且您尝试使用 SOCK_STREAM(TCP 连接),就好像它是面向数据报的(即,作为 SOCK_DGRAM,如 UDP)。

因此,您发送一些构成完整腌制数据集的字节,但服务器不知道特定腌制数据集的开始或结束位置。相反,接收代码会尝试解开碰巧传送给它的任何随机字节块。

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

当然,您永远不应该解开通过网络接收到的数据。看到http://docs.python.org/2/library/pickle.html上的大红框了吗?它之所以存在,是因为如果您编写一个像您在这里展示的那样的服务器,那么您已经编写了一个带有远程任意代码漏洞的服务器,该漏洞大到足以驱动半程。

由于您的数据看起来相当简单且结构化,因此我建议您改用AMP 。

于 2013-03-29T12:14:54.817 回答