2017-04-09 452 views
0

我以前做的項目與標準輸入子管材連接一個遙遠的VIM(我的服務器上),我的客戶,通過標準輸出SSL套接字。我使用Python 3.4。 我的套接字(代碼中的cSock)是SSL封裝的,每次我嘗試打開Vim時我都有同樣的錯誤。在這裏我的代碼:的Python 3.4 ssl.SSLEOFError:EOF發生違反協議(_ssl.c:1638)

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) 

任何解決方案?

回答

0

SSL/TLS是在TCP之上的層。但是,雖然TCP在內核中完成,但SSL/TLS在用戶空間中完成。有因爲這兩個問題:

的第一個問題是,用戶空間,從而做叉內subprocess.Popen當SSL狀態被複制。但是,父對象或子對象中的此套接字上的任何操作都不會與其他進程中的狀態同步,因此,如果兩個進程都主動處理套接字(包括關閉它),則會導致SSL狀態失敗,從而導致連接錯誤。

即使只有子進程處理該問題,fork之後的exec(如subprocess.Popen中所做的)將僅使進程可用的內核文件描述符(在您的案例中爲rvim),而不是用戶空間SSL層,因爲這個用戶空間只在Python進程中。這樣子進程將使用普通的TCP套接字進行通信,而服務器期望SSL。這也會導致連接錯誤並最終導致連接關閉。另見Python3 CGI HTTPS server fails on Unix

我能想到的唯一的辦法是隻保留SSL套接字父和使用單獨的管道(或socketpair)與子進程進行通信。從父級服務器接收的所有數據(使用SSL)應該明確地轉發到子進程,並且應該使用SSL將子進程中的所有數據發送到父級內的服務器。

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) 

我可以忽略它,因爲我的服務器繼續沒有錯誤,但它不是很「乾淨」。你知道爲什麼當我退出Vim時,爲什麼會出現這個錯誤:x或:wq?如果我這樣做,也是沒有問題的:w和之後:q。

+0

嗯,我發現這個問題。 'if buf ==「」:'沒有看到EOF字符,但是「如果buf:'工作得很好。 非常感謝您的幫助@Steffen Ullrich! – Xysto

相關問題