例如,我们实现了一个web视频监控服务器,服务器端采集摄像头数据,客户端使用浏览器通过http请求接收数据。服务器使用推送的方式(multipart/x-mixed-replace)一直使用一个tcp连接向客户端传递数据。这种方式将持续占用一个线程,导致单线程服务器无法处理多客户端请求。
要求:改写程序,在每个线程中处理一个客户端请求,支持多客户端访问。
解决方案:
threading.local()
函数可以创建线程本地数据空间,其下属性对每个线程独立存在。
- 对于线程本地数据:
线程本地数据是特定线程的数据。管理线程本地数据,只需要创建一个local(或者一个子类型)的实例并在实例中储存属性:
mydata = threading.local()
mydata.x = 1
在不同的线程中,实例的值会不同。class threading.local
,一个代表线程本地数据的类。
- 方案示例:
yum install -y numpy opencv* python-qt4
pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-contrib-python==3.4.2.17
import os, cv2, time, struct, threading
from http.server import HTTPServer, BaseHTTPRequestHandler
from socketserver import TCPServer, ThreadingTCPServer
from threading import Thread, RLock
from select import select
class JpegStreamer(Thread):
def __init__(self, camrea):
super().__init__()
self.cap = cv2.VideoCapture(camrea)
self.lock = RLock()
self.pipes = {
}
def register(self):
pr, pw = os.pipe()
self.lock.acquire()
self.pipes[pr] = pw
self.lock.release()
return pr
def unregister(self, pr):
self.lock.acquire()
pw = self.pipes.pop(pr)
self.lock.release()
os.close(pr)
os.close(pw)
def capture(self):
cap = self.cap
while cap.isOpened():
ret, frame = cap.read()
if ret:
ret, data = cv2.imencode('.jpg', frame, (cv2.IMWRITE_JPEG_QUALITY, 40))
yield data.tostring()
def send_frame(self, frame):
n = struct.pack('1', len(frame))
self.<