通过安全(SSL)WebSocket从Python向Python发送消息

时间:2018-11-08 08:53:22

标签: python python-3.x ssl websocket

我有一个C ++应用程序,它嵌入了Python脚本。 C ++应用程序将cv::Mat图像发送到Py脚本,然后运行一些图像识别(通过CNN)。基本思想可以在my gist中找到。

然后我的Python脚本希望通过带有SSL的安全WebSocket将CNN预测的结果发送到另一个应用程序(我相信在Unity中)。

我目前无法访问实际的Unity应用,因此我必须使用一个简单的Python服务器应用来测试实际的“发送”部分。

我对Python中的套接字和SSL没有太多的经验(或知识),所以我希望能有所帮助。

如果我仅使用非安全的HTTP连接,那么一切都会正常,但是当我尝试引入HTTPS和SSL时,会遇到问题。

服务器端:

在上一次尝试中,我使用了以下服务器脚本(取自here):

import asyncio
import pathlib
import ssl
import websockets

async def hello(websocket, path):
    name = await websocket.recv()
    print(f"< {name}")

    ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
    ssl_context.load_cert_chain(
        pathlib.Path(__file__).with_name('cert.pem'), 
        pathlib.Path(__file__).with_name('key_wopasswd.pem'))

start_server = websockets.serve(hello, 'localhost', 443, ssl=ssl_context)

asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

证书和密钥文件是由负责实际接收Unity应用程序的同事给我的。

客户端:

之后,我尝试连接并发送如下消息(片段1 ):

import json
import http.client, ssl
import time

ws = None
def send(msg="lol"):
    global ws
    if ws is None:
        ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
        ssl_context.load_cert_chain('cert.pem', 'key_wopasswd.pem')
        ws = http.client.HTTPSConnection("localhost", 443, context=ssl_context)
        ws.connect()
        print("connected successfully!")
    else:
        jsonString = json.dumps({"Time":int(time.time()), "Message":msg})
        ws.send(jsonString.encode('utf-8'))  

在这种情况下,什么也没发生。

或这样(片段2 ):

import websocket, ssl
import time

ws = None
def send(msg="lol"):
    global ws
    if ws is None: 
        ws = websocket.WebSocket(sslopt={"cert_reqs": ssl.CERT_REQUIRED,
                                         "ssl_version": ssl.PROTOCOL_TLSv1, 
                                         "certfile": "cert.pem", 
                                         "keyfile": "key_wopasswd.pem"})
        ws.connect("wss://localhost:443")        
    else:
        jsonString = json.dumps({"Time":int(time.time()), "Message":msg})        
        ws.send(jsonString.encode('utf-8'))  

在这种情况下,出现以下错误:

Traceback (most recent call last):
  File ".\client2.py", line 21, in send
    ws.connect("wss://localhost:443")
  File "C:\Program Files\Python36\lib\site-packages\websocket\_core.py", line 220, in connect
    options.pop('socket', None))
  File "C:\Program Files\Python36\lib\site-packages\websocket\_http.py", line 126, in connect
    sock = _ssl_socket(sock, options.sslopt, hostname)
  File "C:\Program Files\Python36\lib\site-packages\websocket\_http.py", line 253, in _ssl_socket
    sock = _wrap_sni_socket(sock, sslopt, hostname, check_hostname)
  File "C:\Program Files\Python36\lib\site-packages\websocket\_http.py", line 232, in _wrap_sni_socket
    server_hostname=hostname,
  File "C:\Program Files\Python36\lib\ssl.py", line 401, in wrap_socket
    _context=self, _session=session)
  File "C:\Program Files\Python36\lib\ssl.py", line 808, in __init__
    self.do_handshake()
  File "C:\Program Files\Python36\lib\ssl.py", line 1061, in do_handshake
    self._sslobj.do_handshake()
  File "C:\Program Files\Python36\lib\ssl.py", line 683, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)

我还尝试了一个简单的http.server.HTTPServer,但是唯一的区别是在第一个客户端(片段1 )中,它没有在每次发送后打印消息,而是累积了所有我停止客户端后,收到的消息并全部打印在一起,错误为:代码400,消息错误的请求语法

tl;博士 基本上,我需要的一个很好的例子是如何使用SSL连接一次安全的HTTPS服务器,然后继续发送字符串消息,直到应用停止。

一个小更新:

如果我这样编写客户端,它是有效的,但前提是我在每条消息后关闭并重新打开连接:

import json
import websocket, ssl
import time

ws = None
def send(msg="..."):
    global ws
    if ws is None:
        ws = websocket.WebSocket(sslopt={"cert_reqs": ssl.CERT_NONE,
                                         "ssl_version": ssl.PROTOCOL_TLSv1, 
                                         "certfile": "cert.pem", 
                                         "keyfile": "key_wopasswd.pem"})
        ws.connect("wss://localhost:443")

    jsonString = json.dumps({"Time":int(time.time()), "Message":msg})
    ws.send(jsonString.encode('utf-8'))         
    ws.close()       
    ws = None 

########################
i = 0
while i < 10:
    i = i + 1
    send("i = %d" % i)

0 个答案:

没有答案