好的,所以我试图通过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连接向对方发送消息。我知道这是一个糟糕的代码,但我只需要知道如何让服务器发回消息,因为无论何时我尝试它都会在最后得到错误。
答案 0 :(得分:4)
您的设计似乎在很多层面都被误导了。
首先,您不需要两个插槽来向两个方向发送数据;套接字是双向的。
你可能不希望从服务器回到客户端 - 这可能在localhost测试中有效,但是一旦你部署到互联网,大多数客户端将落后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上工作,并且通过这么小的消息,它可能会在互联网上大部分时间,但 all 时间。
您似乎也对类变量和实例变量之间的区别感到困惑,因为您在SecureIn
和SecureOut
中设置了一堆类变量。这意味着如果你有两个类的实例,它们会共享相同的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。