Reputation: 6795
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!
Upvotes: 0
Views: 131
Reputation: 6795
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:
class MyHTTPServer(HTTPServer):
def handle_error(self, request, client_address):
print(f'HTTP Server got error from {client_address}: {sys.exc_info()[0]}')
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:
HTTP Server got error from ('127.0.0.1', 14420): <class 'ConnectionAbortedError'>
Upvotes: 0