My code is using SSE technique (Server-Sent Events) to send Jpeg images every time a camera-viewer object is updated with a new frame. I'm using Python 3.9.13.
Inside `do_GET I have this code:
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()
And then a loop is used to wait for a new frame and send it over when available:
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
Now everything works well. The client is using this code to read the frame one by one:
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);
};
When the client wants to abort the stream, it calls app.sse.close(). At that time the server doesn't show any log, but after about 1.5 seconds, I'm getting two errors. the first error comes from my exception handler and is really ok:
stream3 got exception: [WinError 10053] An established connection was aborted by the software in your host machine
and another very annoying one from the socket server library:
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
Now my question is: how can I eliminate the error printed from the socket server library? I would really appreciate your help with that!
I finally found a solution.
Instead of creating an instance of HTTPServer within my code, I change it to be an instance of MyHTTPServer which is declared like this:
This way I can control what is printed for this error at the server level, in addition to handling the exception at the do_GET() level .
A typical result from my implementation would be: