0

私は 2 つのアプリケーションを作成しました: クライアントは SQL サーバー (10k 行) からデータを抽出し、ピクルス化されたすべての行をソケット経由で「コレクター」サーバーに送信します。サーバーはツイストを使用し(これは必須です)、すべての行を受信し、それを解凍してデータを別の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

しかし、それは毎回同じではありません。例外 i red の印刷: Exception: pop from empty list Exception: list index out of range Exception: "'" Exception: list assignment index out of range

別の奇妙なエラーは次のとおりです: ファイル "/usr/lib/python2.6/pickle.py", line 1124, in find_class import (module) exceptions.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

書き込み間に遅延を追加しても問題がないため、問題がピクルではなく、データの転送に関連していることは明らかです。

1 つのオプションは、サーバーが処理できるよりも速くクライアントがソケットにデータを書き込み続けることであり、その結果、バッファ オーバーフローとパケット損失が発生します。

または、潜在的に同時にソケットに書き込む複数のスレッドがありますか?

于 2013-03-29T05:47:09.650 に答える
1

プロトコルにはフレーミングがなく、SOCK_STREAM (TCP 接続) をデータグラム指向であるかのように (つまり、UDP のような SOCK_DGRAM として) 使用しようとしています。

したがって、完全な pickle データセットを構成するいくつかのバイトを送信しますが、サーバーは特定の pickle データセットがどこで開始または終了するかを認識していません。代わりに、受信側のコードは、たまたま配信されたバイトのランダムなチャンクを unpickle しようとします。

あなたが発見したように、これは時々うまくいきます。ただし、 に渡すバイトがsock.sendall単一のグループとして に配信されるという保証はありませんdataReceived。受信者がメッセージの境界を発見できるように、フレーミングを追加する必要があります。これにはいくつかのアプローチがあります。1 つの方法は、長さのプレフィックスを追加することです。次に、受信者は待機するバイト数を認識し、正しい数を受信したときにそれらを unpickle できます。

もちろん、ネットワーク経由で受信したデータを unpickle してはいけません。http://docs.python.org/2/library/pickle.htmlの大きな赤いボックスを参照してください。ここで示しているようなサーバーを作成すると、リモートの任意のコードの脆弱性を備えたサーバーを作成して、セミスルーを実行するのに十分な大きさになるためです。

あなたのデータはかなり単純で構造化されているように見えるので、代わりにAMPを検討することをお勧めします。

于 2013-03-29T12:14:54.817 に答える