Python 3.4 ssl.SSLEOFError:EOF违反协议(_ssl.c:1638)

时间:2017-04-09 14:27:22

标签: python-3.x ssl

我的项目是将远程vim(在我的服务器上)连接到我的客户端,使用子进程stdin的pIPE,stdout通过SSL套接字。我使用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)

任何解决方案?

2 个答案:

答案 0 :(得分:0)

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

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

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

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

答案 1 :(得分:0)

感谢您的回复! 我现在正在使用socketpair(),就像你向我解释的那样,它好多了!我可以使用我的遥远的vim版本没有错误。但是一旦我想退出:wq或:x我也有同样的错误。但是如果我使用的话就没关系:w AND AFTER:q。

Traceback (most recent call last):
  File "/usr/lib/python3.4/threading.py", line 920, in _bootstrap_inner
    self.run()
  File ".../appcm/release/src/server/edition.py", line 73, 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)

我可以忽略它,因为我的服务器在此之后继续没有错误,但它不是很清楚"。你知道为什么我在使用:x或:wq退出Vim时出现了这个错误吗?如果我这样做,那么也没有问题:w和之后:q。