use*_*054 4 python sockets ssl 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()
Run Code Online (Sandbox Code Playgroud)
我收到此错误:
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
Run Code Online (Sandbox Code Playgroud)
或者,我尝试让独立服务器向所有客户端发送广播消息。我到处搜索,但似乎找不到使用 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')]
Run Code Online (Sandbox Code Playgroud)
从这段代码:
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')
Run Code Online (Sandbox Code Playgroud)
请帮助我 StackOverFlow,你是我唯一的希望。我知道这应该很容易,但此时我的大脑太紧张了,我无法再思考了。
另外,我对 python 还很陌生,所以很可能它的操作/加载类/等方式有一些我不明白的地方。
编辑:好的,我知道这段代码很糟糕。它不是一个即将上市的产品,它永远不会上线,这只是我试图让一个概念发挥作用,这个概念是:让服务器和客户端通过 python ssl 连接相互发送消息。
我知道这是糟糕的代码,但我只需要知道如何让服务器发回消息,因为每当我尝试它时,最后都会收到错误。
你的设计似乎在很多层面上都被误导了。
\n\n首先,您不需要两个套接字来双向发送数据;套接字是双向的。
\n\n而且您可能不想从服务器返回到客户端 \xe2\x80\x94 的连接,这可能在本地主机测试中工作,但一旦部署到互联网,大多数客户端将位于 NAT 路由器后面,并且不会'没有可以连接的公共地址。
\n\n同时,你的逻辑很奇怪。您在一个方向启动连接,然后休眠 6 秒,然后在另一个方向启动连接。你为什么想这么做?
\n\n如果服务器在SecureOut客户端调用它之前甚至大约同时调用它,SecureIn它会在有人监听之前尝试连接,这将准确地得到您所看到的错误。
另外,每个线程都有一个非常奇怪的运行循环:
\n\ndef run(self):\n while True:\n self.s.listen(5)\n (connection, address) = self.s.accept()\n print repr(connection.recv(5570))\nRun Code Online (Sandbox Code Playgroud)\n\n它一次只接受一个连接,从中读取一次,然后泄漏该连接,不再与其通信,然后去获取下一个客户端。(我也不确定listen(5)在已经监听的套接字上再次调用是否实际上有效,或者它做了什么。)当然它不可能完成。(这不太正确\xe2\x80\x94,例如,如果客户端连接然后在调用之前消失recv,你可能会得到一个异常,但你没有捕获到,所以你的程序将退出\xe2\x80 \xa6) 这是你想要的吗?
还有,为什么recv(5570)?该数字是要读取的最大字节数,而不是端口号。
为什么要打印repr字符串的 ?
同时,您是否意识到recv,无论您传递的缓冲区长度是什么,都永远无法保证获得完整的消息(或者如果您有一个发送了多条消息的客户端,则只能获得一条消息而不是两条消息)?它几乎肯定可以在本地主机上工作,并且通过如此小的消息,它可能在互联网上的大部分时间都可以工作,但并非总是如此。
SecureIn您似乎还对类变量和实例变量之间的区别感到困惑,因为您在和中设置了一堆类变量SecureOut。这意味着,如果您可以拥有该类的两个实例,它们将共享相同的SSL.Context实例,等等。即使您在现实生活中不需要同时拥有两个实例,为了测试,您几乎肯定会想要创建一个新实例,您将希望创建一个新套接字等,而不是继续使用旧实例。所以代替这个:
class SecureIn(threading.Thread):\n context = SSL.Context(SSL.SSLv23_METHOD)\n context.use_privatekey_file('key')\n context.use_certificate_file('cert')\n \xe2\x80\xa6\nRun Code Online (Sandbox Code Playgroud)\n\n做这个:
\n\nclass SecureIn(threading.Thread):\n def __init__(self):\n self.context = SSL.Context(SSL.SSLv23_METHOD)\n self.context.use_privatekey_file('key')\n self.context.use_certificate_file('cert')\n \xe2\x80\xa6\nRun Code Online (Sandbox Code Playgroud)\n\n(当然,或者您可以将其放入 run 方法中。)
\n\n基本上,无论有没有 SSL,这都不可能做任何有用的事情。我建议您退后一步,阅读一些教程,编写一些适用于普通 TCP 套接字的东西,然后担心如何对其进行 SSL 化。
\n