【问题标题】:pyOpenSSL SSL3_WRITE_PENDING:bad write retry, return self._sslobj.write(data) error: [Errno 10054]pyOpenSSL SSL3_WRITE_PENDING:错误的写入重试,返回 self._sslobj.write(data) 错误:[Errno 10054]
【发布时间】:2013-12-21 04:28:50
【问题描述】:

我现在正在用 Python 开发一个聊天服务器。 我正在将 pyOpenSSL 应用于我为测试而制作的聊天服务器和虚拟客户端。 但是,每当从虚拟客户端向服务器发送短信和照片文件时,pyOpenSSL 都会返回严重错误,这促使我停止使用 pyOpenSSL,如下所示。

send_text_message() : exception : [Errno 1] _ssl.c:1309: error:1409F07F:SSL routines:SSL3_WRITE_PENDING:bad write retry
send_text_message() : exception : [Errno 1] _ssl.c:1309: error:1409F07F:SSL routines:SSL3_WRITE_PENDING:bad write retry
send_text_message() : exception : [Errno 1] _ssl.c:1309: error:1409F07F:SSL routines:SSL3_WRITE_PENDING:bad write retry
send_text_message() : exception : [Errno 1] _ssl.c:1309: error:1409F07F:SSL routines:SSL3_WRITE_PENDING:bad write retry
send_text_message() : exception : [Errno 1] _ssl.c:1309: error:1409F07F:SSL routines:SSL3_WRITE_PENDING:bad write retry
send_text_message() : exception : [Errno 1] _ssl.c:1309: error:1409F07F:SSL routines:SSL3_WRITE_PENDING:bad write retry
send_text_message() : exception : [Errno 1] _ssl.c:1309: error:1409F07F:SSL routines:SSL3_WRITE_PENDING:bad write retry

你能告诉我如何解决这个错误吗? 还有一个错误导致虚拟客户端死亡。

[client1|chatting1A] socket closed : device_id : client1, client_chatting_id : chatting1A, error : [Errno 10053] 
Exception in thread Thread-8:
Traceback (most recent call last):
  File "C:\Python27\lib\threading.py", line 810, in __bootstrap_inner
    self.run()
  File "C:\Python27\lib\threading.py", line 1082, in run
    self.function(*self.args, **self.kwargs)
  File "D:\temp\uTok1\uTokSocketServer\com\rurusoft\utok\DummyClient.py", line 97, in send_photo_message
    sock.write(message)
  File "C:\Python27\lib\ssl.py", line 172, in write
    return self._sslobj.write(data)
error: [Errno 10054]

没有 pyOpenSSL,虚拟客户端和服务器运行良好。应用 pyOpenSSL 会导致意想不到的问题:(。 如果您遇到问题或有解决问题的方法,请告诉我。 ....如果没有解决该错误的方法,我宁愿找出其他不使用 OpenSSL 的替代方案。 或者您知道任何可以加密/解密机器之间传输的聊天消息和个人文件的替代方案吗?

虽然我在写入(发送)数据之前已经将要发送的数据存储在局部变量中,但每次都会发生错误。


  json_encoded = json.dumps(data)
          while True:
              try:
                  sock.write(json_encoded)
                  break
              except Exception, e:
                  Log.print_log(self.LOG_TAG, 'send_text_message() : exception : %s' % (e))
                  time.sleep(0.05)

已解决: 正如@David Schwartz 评论的那样,以下代码解决了上面的问题。

    import StringIO
    ...
    io = StringIO.StringIO()
    io.write(json.dumps(data))
    buffer = io.getvalue()
    while True:
        try:
            sock.write(buffer)
            break
    ...
    

【问题讨论】:

    标签: python sockets openssl pyopenssl


    【解决方案1】:

    OpenSSL 对如何重试写入有非常严格的要求——特别是缓冲区的地址和内容不得更改。当你重试写入时,你必须用 exact 相同的缓冲区重试(相同的内容是不够的,当然,不同的内容是绝对禁止的)。

    比如这个坏了:

    ssl_socket.send(send_buffer.getvalue())
    

    由于你没有存储你传递给send的值,如果你需要重试send,你怎么能传递相同的值呢?不能保证对getvalue 的后续调用将返回相同的结果。如果缓冲区移动,重复此操作可能会产生错误的写入重试,它随时都可能发生。

    更新:您的代码不会阻止缓冲区更改。没有不改变反映缓冲区的对象。试试:

    io = StringIO()
    json.dumps(data, io)
    buffer = io.getvalue()
    
          while True:
              try:
                  sock.write(buffer)
                  break
    

    这里,io 是缓冲区,getvalue 只被调用一次。

    【讨论】:

    • 我在问题的底部添加了更多关于您的回答的内容。如果可以的话,你能不能看一下,说几句?
    • @DavidSchwartz...谢谢大卫,您的回答对我有很大帮助。我更新了我的问题,它稍微修改了你的代码,以便它可以工作。周末愉快~!
    • pyOpenSSL 实际上设置了使 OpenSSL 在调用 SSL_write 时不关心缓冲区是否移动的标志。具体来说,它总是使用SSL_CTX_set_mode 将模式设置为SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_AUTO_RETRY
    • @Jean-PaulCalderone 的上述声明不再正确:github.com/pyca/pyopenssl/blob/master/OpenSSL/SSL.py
    猜你喜欢
    • 2013-01-19
    • 2018-02-05
    • 2012-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-07
    • 1970-01-01
    • 2019-12-09
    相关资源
    最近更新 更多