【问题标题】:Python 3.4 ssl.SSLEOFError: EOF occurred in violation of protocol (_ssl.c:1638)Python 3.4 ssl.SSLEOFError: EOF 发生违反协议 (_ssl.c:1638)
【发布时间】:2017-04-10 15:45:55
【问题描述】:

我的项目是通过 SSL 套接字使用子进程 stdin、stdout 的 PIPE 将远程 vim(在我的服务器上)连接到我的客户端。我使用 Python 3.4。 我的套接字(代码中的 cSock)是 SSL 包装的,每次我尝试打开 Vim 时都会遇到同样的错误。这是我的代码:

vimProc = sp.Popen(["rvim", file], bufsize=0, stdin=sp.PIPE, stdout=sp.PIPE)

cSock.settimeout(1)

rec = Reception(cSock, vimProc)
emi = Emission(cSock, vimProc)

rec.start()
emi.start()

rec.join()
emi.join()

这里是我的接收和发射线程

class Reception(threading.Thread):

def __init__(self, sock, proc):
    threading.Thread.__init__(self)
    self.sock = sock
    self.proc = proc

def run(self):
    while self.proc.poll() == None:
        try:
            self.proc.communicate(self.sock.recv(1))
        except socket.timeout:
            pass


class Emission(threading.Thread):

def __init__(self, sock, proc):
    threading.Thread.__init__(self)
    self.sock = sock
    self.proc = proc

def run(self):
    while self.proc.poll() == None:
        try:
            outs = self.proc.stdout.read(1)
            if outs == "":
                print("EOF reached")
            else:
                self.sock.send(outs)

        except socket.timeout: 
            pass

这里是回溯:

Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python3.4/threading.py", line 920, in _bootstrap_inner
    self.run()
  File ".../server/edition.py", line 62, in run
    self.sock.send(outs)
  File "/usr/lib/python3.4/ssl.py", line 678, in send
    v = self._sslobj.write(data)
ssl.SSLEOFError: EOF occurred in violation of protocol (_ssl.c:1638)

有什么办法吗?

【问题讨论】:

    标签: python-3.x ssl


    【解决方案1】:

    SSL/TLS 是 TCP 之上的一层。但是,虽然 TCP 在内核中完成,但 SSL/TLS 在用户空间中完成。因此有两个问题:

    第一个问题是在subprocess.Popen 内部进行分叉时,用户空间和 SSL 状态会重复。但是在父进程或子进程中对此套接字的任何操作都不会与其他进程中的状态同步,因此如果两个进程都主动处理套接字(包括关闭它),则会导致 SSL 状态失败,从而导致连接出错。

    即使只有子进程处理问题,fork 之后的 exec(如在 subprocess.Popen 中所做的那样)只会使内核文件描述符可用于进程(在您的情况下为 rvim),而不是用户space SSL 层,因为此用户空间仅在 Python 进程内。这样子进程将使用普通的 TCP 套接字进行通信,而服务器需要 SSL。这也会导致连接错误并最终关闭连接。另见Python3 CGI HTTPS server fails on Unix

    我能想到的唯一方法是将 SSL 套接字仅保留在父进程中,并使用单独的管道(或套接字对)与子进程通信。从父级服务器接收到的所有数据(使用 SSL)都应该以明文形式转发给子进程,来自子进程的所有数据都应该使用 SSL 发送到父级内部的服务器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-15
      • 1970-01-01
      相关资源
      最近更新 更多