Как избежать потери данных, используя socket и pyqt с многопоточностью - PullRequest
0 голосов
/ 13 февраля 2020

Я постоянно и одновременно получаю изображения с нескольких клиентов на один сервер. Я использовал pyqt5 и QRunnable для достижения этой цели. Код примет клиентское соединение, передаст его потоку и начнет передавать потоковое изображение и данные вместе с ним. Однако я заметил, что некоторые изображения не принимаются / отбрасываются в каждом потоке. Вот мой код потока на стороне сервера, который передает изображения от клиентов:

class threading(QRunnable):
    def __init__(self,t1,t2,index,ttype,ptype,test):
        super(threading,self).__init__()

        self.t1=t1
        self.t2=t2

        self.ch=index
        self.ttype=ttype
        self.ptype=ptype
        self.test=test
        self.top1=""
        self.bot1=""
        self.img1=np.zeros((161,182,3),dtype=np.uint8)
        self.signals=WorkerSignals()
        self.top_process=top_data()
        self.bot_process=bot_data()

    def recvall(self,sock, count):
        buf = b''
        while count:
            if sock:
                newbuf = sock.recv(count)
            if not newbuf: return None
            buf += newbuf
            count -= len(newbuf)
        return buf

    def stream(self,conn):
        length = '0'
        length = (self.recvall(conn,5))
        print ('data len',length)
        if(length[3]==35):
            stringData = self.recvall(conn, int(length[:3]))

        elif(length[4]==35):
            stringData = self.recvall(conn, int(length[:4]))

        else:
            stringData = self.recvall(conn, int(length))
            print('act len',int(length))
            #print('sting 3',stringData)

        data = np.frombuffer(stringData, dtype='uint8')
        decimg = cv2.imdecode(data,1)
        #conn.close()
        return decimg

    def run(self):

        c=1
        print('thread',self.ch,self.test)
        global b1,b2,b3,b4,b5,b6
        if self.test==2:
            for fille in os.listdir(b1[self.ch-1]):
                if fille.endswith('.jpg'):
                    os.remove(b1[self.ch-1]+fille)
            for fille in os.listdir(b2[self.ch-1]):
                if fille.endswith('.jpg'):
                    os.remove(b2[self.ch-1]+fille)
            for fille in os.listdir(b3[self.ch-1]):
                if fille.endswith('.jpg'):
                    os.remove(b3[self.ch-1]+fille)
            for fille in os.listdir(b4[self.ch-1]):
                if fille.endswith('.jpg'):
                    os.remove(b4[self.ch-1]+fille)
            for fille in os.listdir(b5[self.ch-1]):
                if fille.endswith('.jpg'):
                    os.remove(b5[self.ch-1]+fille)
            for fille in os.listdir(b6[self.ch-1]):
                if fille.endswith('.jpg'):
                    os.remove(b6[self.ch-1]+fille)
            for fille in os.listdir(b7[self.ch-1]):
                if fille.endswith('.jpg'):
                    os.remove(b7[self.ch-1]+fille)
        while not stopEvent.is_set():

            img1=self.stream(self.t1)
            d1=convertimg(img1)
            if self.ch>=7:
                self.bot1=self.recvall(self.t2,30)
            if self.ch<=6:
                self.top1=self.recvall(self.t2,40)
            if self.test>0:
                if self.ch<=6:
                    self.top_process.taskvar(self.top1,img1,self.ttype,self.ptype,self.test,self.ch)
                    self.top_process.start()
                    self.top_process.signals.finish.connect(self.sendata,Qt.DirectConnection)
                if self.ch>=7:
                    self.bot_process.taskvar(self.bot1,img1,self.ttype,self.ptype,self.test,self.ch)
                    self.bot_process.start()


            if self.ch==1:
                self.signals.i1.emit(d1)

            if self.ch==2:
                self.signals.i2.emit(d1)

            if self.ch==3:
                self.signals.i3.emit(d1)

            if self.ch==4:
                self.signals.i4.emit(d1)

            if self.ch==5:
                self.signals.i5.emit(d1)

            if self.ch==6:
                self.signals.i6.emit(d1)

            if self.ch==7:
                self.signals.i7.emit(d1)

            if self.ch==8:
                self.signals.i8.emit(d1)

            if self.ch==9:
                self.signals.i9.emit(d1)

            if self.ch==10:
                self.signals.i10.emit(d1)

            if self.ch==11:
                self.signals.i11.emit(d1)

            if self.ch==12:
                self.signals.i12.emit(d1)
            c=c+1

Существует 12 клиентов, которые одновременно отправляют одно изображение и одну строку на сервер. Может кто-нибудь сказать мне, почему происходит потеря данных ?? Это состояние гонки или ошибка в получении кода.

1 Ответ

0 голосов
/ 13 февраля 2020

Один из способов решить эту проблему - добавить мьютекс.

from PyQt5.QtCore import QMutex

Вы помещаете его в свой init:

self.mutex = QMutex()

Затем вы блокируете ту часть кода, которая получает картинка:

if self.mutex.tryLock():
    # receive picture

self.mutex.unlock()

Для получения дополнительной информации и примеров вы можете проверить официальную документацию QMutex

Дайте мне знать, если это работает!

...