簡體   English   中英

Python SSL Socket:從服務器和客戶端接收和發送

[英]Python SSL Socket: receiving and sending from both server and client

好的,所以我試圖通過SSL套接字連接在服務器和客戶端之間來回通信。 我認為最好的方法就是在每個中實現2個線程,每個線程分別充當服務器和客戶端。但是當我實現這個代碼時(顯然在其他服務器/客戶端使用相對的相應端口) :

#secserv.py

import socket
from OpenSSL import SSL
import threading
import time

class SecureIn(threading.Thread):
  context = SSL.Context(SSL.SSLv23_METHOD)
  context.use_privatekey_file('key')
  context.use_certificate_file('cert')

  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  s = SSL.Connection(context, s)
  s.bind(('', 5570))
  def run(self):
    while True:
      self.s.listen(5)
      (connection, address) = self.s.accept()
      print repr(connection.recv(5570))


class SecureOut(threading.Thread):
  time.sleep(6)
  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  s.connect(('localhost', 12345))
  sslSocket = socket.ssl(s)
  print repr(sslSocket.server())
  print repr(sslSocket.issuer())
  def run(self):
    sslSocket.write('Hello secure socket\n')

  s.close()


si = SecureIn()
si.start()
time.sleep(6)
so = SecureOut()
so.start()

我收到此錯誤:

Traceback (most recent call last):
  File "secserv.py", line 25, in <module>
    class SecureOut(threading.Thread):
  File "secserv.py", line 28, in SecureOut
    s.connect(('localhost', 12345))
  File "/usr/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
socket.error: [Errno 111] Connection refused

或者,我嘗試使用獨立服務器向所有客戶端發送廣播消息。 我已經搜索了高低,但我似乎無法找到一種工作方式來使用SSL套接字,只有常規套接字。 當我嘗試s.write()s.sendall()我收到此錯誤:

Traceback (most recent call last):
  File "secserv.py", line 19, in <module>
    s.write('hello client\n')
OpenSSL.SSL.Error: [('SSL routines', 'SSL_write', 'uninitialized')]

從這段代碼:

import socket
from OpenSSL import SSL
context = SSL.Context(SSL.SSLv23_METHOD)
context.use_privatekey_file('key')
context.use_certificate_file('cert') 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s = SSL.Connection(context, s)
s.bind(('', 12345))
while True:
    s.listen(5) 
    (connection, address) = s.accept()
    print repr(connection.recv(12345))
    #This could also be s.sendall()
    s.write('hello client\n')

請幫我StackOverFlow,你是我唯一的希望。 我知道這應該很容易,但是我的大腦在這一點上非常緊張,我再也想不到了。

另外,我對python很新,所以很有可能它的操作方式/加載類/等等,我只是沒有得到。

編輯:好的,我知道這段代碼很糟糕。 它不是一個推向市場的產品,它永遠不會在現場運行,這只是我試圖讓一個概念起作用,而這個概念是:讓服務器和客戶端通過python ssl連接向對方發送消息。

我知道這是可怕的代碼,但我只需要知道如何讓服務器發回消息,因為無論何時我嘗試它都會在最后得到錯誤。

您的設計似乎在許多層面上都是錯誤的。

首先,您不需要兩個插槽來向兩個方向發送數據; 套接字是雙向的。

並且您可能不希望從服務器返回到客戶端 - 這可能在localhost測試中起作用,但是一旦部署到Internet,大多數客戶端將位於NAT路由器后面,並且不會有公共地址你可以連接到。

同時,你的邏輯很奇怪。 您在一個方向上開始連接,然后睡6秒,然后在另一個方向上開始連接。 你為什么想這么做?

如果服務器調用其SecureOut之前,甚至在同一時間,作為客戶端調用其SecureIn ,它會嘗試連接有任何人聽,這將讓正是你所看到的錯誤了。

此外,每個線程都有一個非常奇怪的運行循環:

def run(self):
    while True:
        self.s.listen(5)
        (connection, address) = self.s.accept()
        print repr(connection.recv(5570))

這一次只接受一個連接,從中讀取一次,然后泄漏連接,再也不與它通話,然后去獲取下一個客戶端。 (我也不確定在已經正在收聽的套接字上再次調用listen(5)是否真的有效。或者它的功能。當然,它無法完成。 (這不是真的 - 例如,如果一個客戶端連接然后在你調用recv之前消失,你可能會得到一個例外,你沒有抓到,所以你的程序將退出...)這就是你想要的?

另外,為什么recv(5570) 該數字是要讀取的最大字節數,而不是端口號。

為什么打印字符串的repr

同時,你是否意識到recv ,無論你為緩沖區長度傳遞什么,都不能保證獲得整個消息(或者只獲得一條消息而不是兩條消息,如果你有一個客戶端發送了多個消息)? 它幾乎可以肯定地在localhost上工作,並且通過這么小的消息它可能在互聯網上大部分時間都可以工作,但不是所有的時間。

您似乎也對類變量和實例變量之間的區別感到困惑,因為您在SecureInSecureOut設置了一堆類變量。 這意味着如果你有兩個類的實例,它們會共享相同的SSL.Context等。即使你不需要在現實生活中同時擁有兩個實例,為了測試你幾乎肯定會想要創建一個新實例,你會想要創建一個新的套接字等,而不是繼續使用舊的。 所以不是這樣的:

class SecureIn(threading.Thread):
  context = SSL.Context(SSL.SSLv23_METHOD)
  context.use_privatekey_file('key')
  context.use_certificate_file('cert')
  …

做這個:

class SecureIn(threading.Thread):
  def __init__(self):
    self.context = SSL.Context(SSL.SSLv23_METHOD)
    self.context.use_privatekey_file('key')
    self.context.use_certificate_file('cert')
    …

(或者你可以把它放在run方法中,當然。)

基本上,無論是否使用SSL,這都不太可能有用。 我建議你退后一步,閱讀一些教程,並編寫適用於普通TCP套接字的東西,然后擔心如何對其進行SSL-ize。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM