Python:Windows VistaEgenixで2.7.2PyOpenSSL:0.13.0
プロキシサービスを作成しようとしています。基本的に、プロキシサービスは通常のソケットとSSLソケットをリッスンし、2つの間でデータを中継します。
半信頼性のあるデータを中継することはできますが、SSLソケットのもう一方の端にあるサーバーがデータの送信を完了すると、読み取ることができるデータがまだあるという偽の信号を受け取ります。コードは基本的に次のようになります。
(rs, ws, xs) = select.select([client, sslserver], [], [])
for r in rs:
if r == client:
# tons of client code
elif r == sslserver:
(rs, ws, xs) = select.select([sslserver], [], [], 0)
print 'Reading server: %s, %s' % (len(rs), server.pending())
while len(rs) > 0 or sslserver.pending() > 0:
t = sslserver.read(sslserver.pending())
# Do more useful stuff
(rs, ws, xs) = select.select([sslserver], [], [], 0)
このコードではReading server: 1, 0
、読み取りブロックに入る前にテキストが表示されることがあります。実際に実行するt = sslserver.read(sslserver.pending())
と、結果はトスアップになります。EOF例外が頻繁に発生します(SSL.SysCallError()[1] =='予期しないEOF')。問題は、これが真のEOFである場合もあれば、SSLがデータを利用できない場合もあるということです。
しかし、このように読むように読み取り行を変更すると
t = sslserver.read(4096)
ほとんどのソケット読み取りコードでは、EOFを示すものを取得する代わりに(通常のソケットでは!selectは、ソケットが読み取りの準備ができていることを示します。読み取るデータがないため、すぐにデータを返しません!)、読み取るデータが残っていない場合、私のコードはブロックするだけです。もちろん、これは意味がありません。結局のところ、ソケットは読み取りの準備ができています。EOFが復号化フェーズを通過するまでブロックする必要があります。
しかし、そうではありません。それは永続的なブロックです。
私のオプションは何ですか?select.selectはPyOpenSSLソケットでは安全ではないと私は絶対に信じています。通常のソケットでSSLソケットを監視する他の方法はありますか、それともSSLソケットを別のスレッドに移動し、通常のソケットを使用してデータをメインスレッドに中継する必要がありますか?