0

次のようなデータを受信するためのコードをいくつか取得しました: (SSL が使用されています)

sockListToCheck = self.getSocketList(self.clientSocketsWTTL)
        socksReady, w, e = select.select(sockListToCheck,[],[], d_consts.SELECT_SEC)

        if not socksReady: #list empty
            print 'not ready'
            return #nothing received yet so don't change anything

        leftInError = False
        #we have something
        for sock in socksReady:
            dataBuf = ""
            c1 = 5
            c2 = 5
            while True:
                try:
                    dat = sock.recv(d_consts.BUF_SIZE) # read what is there to read
                    dataBuf += dat
                    print(dat), len(dat)
                    if len(dat) < d_consts.BUF_SIZE and c1 == 0:
                        c1 -= 1
                        print 'about to break'
                        break
                except ssl.SSLError as e:
                    #print 'trying to read '
                    # Ignore the SSL equivalent of EWOULDBLOCK, but re-raise other errors
                    #print e
                    if e.errno != ssl.SSL_ERROR_WANT_READ:
                        print 'serious ssl error'
                        sock.shutdown(socket.SHUT_RDWR)
                        sock.close() #close
                        leftInError = True
                    else: 
                        if c2 == 0:
                            break
                        c2 -= 1
                        continue

            if (leftInError):
                leftInError = False
                print 'left error'
                continue

大幅な遅延があると問題が発生するので、それらのカウンターを追加しました。私の問題は、メッセージの大きさがわからない場合、受信を停止するタイミングがわからないことです。以前は、受信量がバッファよりも少ないときに中断していましたが、とにかくこれが発生することがあり、すべてのデータが到着したわけではないようです. 他の方法はありますか?多分タイムアウトか何か?

4

2 に答える 2

1

これは、ネットワーク プログラミングの一般的な問題です。答えは、ほとんどの場合、生のソケットを使用すべきではないということです。

通常、私はØMQに切り替えることをお勧めします。それは素晴らしいライブラリであり、TCP のバイト ストリームの代わりにメッセージの観点から作業できるからです。それはあなたが実際にほとんどの場合必要とするものです.

しかし残念なことに、現在 ØMQは SSL でうまく動作しません。したがって、当然のことながら、次の 2 つのオプションがあります。

  1. 定型コードをたくさん書く。ワイヤ プロトコル (少なくとも「メッセージ長」フィールドを含む) と、ソケットからバイトを慎重に読み取り、カウントするコードが必要です。
  2. いくつかの既存のライブラリを使用します。最初に頭に浮かぶのは、SSLをサポートするRabbitMQなどのメッセージ ブローカーを使用することです。
  3. より急進的な解決策 (しかし、私は最も素晴らしい解決策だと思います) は、TCP を完全に取り除き、より強力なプロトコル (例: SCTP ) に移行することです。おそらく、このオプションを選択するべきではありません…</li>

最初のオプションを選択した場合。

まず、メッセージを送信する前に、その長さを何らかの固定長形式 (例: 4 バイトの符号なし整数) で送信します。そしていま:

  1. バッファ (バイトのリスト) を作成します。
  2. 4バイトになるまで、ソケットからの読み取りとこのバッファへの追加を続けます。
  3. バッファの長さが 4 以上の場合、最初の 4 バイトを取り除き、残りを保持します。

    if len(buffer) >= 4:
        expected_length = int(buffer[:4])
        buffer = buffer[4:]
    
  4. これで、長さが になるまでバッファにバイトを受信し続けますexpected_length
  5. len(buffer) >= expected_lengthメッセージを受け取ったとき。

同様のものがPython Sockets HOWTOに示されていますが、固定長のメッセージを想定しています。

于 2013-06-08T09:51:11.510 に答える