当客户端优雅地关闭 SSE 时处理 Python HTTPServer 中的套接字错误

问题描述 投票:0回答:1

我的代码使用 SSE 技术(服务器发送事件)在每次用新帧更新相机查看器对象时发送 Jpeg 图像。我正在使用 Python 3.9.13

在 `do_GET 里面我有这个代码:

self.send_response(200)
self.send_header("Content-Type", "text/event-stream")
self.send_header("Cache-Control", "no-cache")
self.send_header("Connection", "keep-alive")
self.end_headers()

然后使用循环来等待新帧并在可用时将其发送出去:

counter = g_cam_viewer.counter - 1
while True:
    if counter < (g_cam_viewer.counter):
        counter = g_cam_viewer.counter
        _, image_data = cv2.imencode('.jpg', g_cam_viewer.last_frame)
        image_data_bytes = image_data.tobytes()

        # Send the JPEG image data as SSE data
        image_base64 = base64.b64encode(image_data_bytes)
        image_frame = b'data: ' + image_base64 + b'\n\n'

        try:
            self.wfile.write(image_frame)
            self.wfile.flush()
        except (OSError, socket.error) as e:
            print('stream3 got exception: ' + str(e))
            return  # client disconnected, release thread
        except Exception as e:
            print('stream2 got exception: ' + str(e))
            return  # client disconnected, release thread
    time.sleep(0.05)  # allow new frame to be ready

现在一切正常。客户端正在使用这段代码来一一读取帧:

app.sse = new EventSource(app.stream_url);
app.sse.onmessage = (e) => {
    app.frame_count += 1;
    console.log('frame count: ', app.frame_count);
    var data = `data:image/jpeg;base64,${e.data}`;
    app.ui.imgStream.attr('src', data);
};
app.sse.onerror = (e) => {
    console.warn('error: ', e);
};

当客户端想要中止流时,它会调用

app.sse.close()
。当时服务器没有显示任何日志,但大约 1.5 秒后,我收到两个错误。第一个错误来自我的异常处理程序,而且真的没问题:

stream3 出现异常:[WinError 10053] 已建立连接 被主机中的软件中止

还有来自套接字服务器库的另一个非常烦人的:

Exception occurred during processing of request from ('127.0.0.1', 17079)
Traceback (most recent call last):
  File "C:\Users\LabUser\...\lib\socketserver.py", line 316, in _handle_request_noblock
    self.process_request(request, client_address)
  File "C:\Users\LabUser\...\lib\socketserver.py", line 347, in process_request
    self.finish_request(request, client_address)
  File "C:\Users\LabUser\...\lib\socketserver.py", line 360, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "C:\Users\LabUser\...\lib\socketserver.py", line 747, in __init__
    self.handle()
  File "C:\Users\LabUser\...\lib\http\server.py", line 427, in handle
    self.handle_one_request()
  File "C:\Users\LabUser\...\lib\http\server.py", line 393, in handle_one_request
    self.raw_requestline = self.rfile.readline(65537)
  File "C:\Users\LabUser\...\lib\socket.py", line 704, in readinto
    return self._sock.recv_into(b)
ConnectionAbortedError: [WinError 10053] An established connection was aborted by the software in your host machine

现在我的问题是:如何消除从套接字服务器库打印的错误?我非常感谢您的帮助!

server-sent-events basehttpserver basehttprequesthandler
1个回答
0
投票

我终于找到解决办法了。

我没有在代码中创建 HTTPServer 的实例,而是将其更改为 MyHTTPServer 的实例,其声明如下:

class MyHTTPServer(HTTPServer):
    def handle_error(self, request, client_address):
        print(f'HTTP Server got error from {client_address}: {sys.exc_info()[0]}')

这样,除了在 do_GET() 级别处理异常之外,我还可以在服务器级别控制此错误的打印内容。

我的实施的典型结果是:

HTTP 服务器从 ('127.0.0.1', 14420) 收到错误:

© www.soinside.com 2019 - 2024. All rights reserved.