Как правильно отключить сокет, который транслирует видео с веб-камеры? - PullRequest
0 голосов
/ 13 февраля 2019

Я пытаюсь передать потоковое видео с моего ноутбука на компьютер для манипуляции cv2.Поток работает, но я не совсем уверен, что делать с закрытием сокета.

У меня нет веб-камеры на рабочем столе, поэтому я хотел попробовать запустить потоковую веб-камеру для своих ноутбуков, чтобы узнать cv2 на кадрах,Я новичок в сокетах, я просмотрел документацию и сделал много поисков, чтобы продвинуться так далеко, хотя большая часть того, что у меня сейчас есть, была скопирована.Я не совсем уверен, где искать, как правильно отключить сокеты при потоковой передаче видеоданных с помощью cv2.Я попытался использовать с socket.socket (...) как s: чтобы закрыть разрывы соединения через некоторое время и попробовать циклы, которые переходят в shutdown (socket.SHUT_WR и close (), и я пытался завершить программу наи клиент, и сервер.

    #server.py

    import socket
    import cv2
    import pickle
    import struct
    def main():
        HOST=''
        PORT=12397    
        with socket.socket(socket.AF_INET,socket.SOCK_STREAM) as s:
            print('Socket created')
            s.bind((HOST,PORT))
            print('Socket bind complete')
            s.listen(10)
            print('Socket now listening')
            conn,addr=s.accept()

            data = b""
            payload_size = struct.calcsize(">L")
            while True:
                try:
                    key = cv2.waitKey(20) & 0xFF
                    while len(data) < payload_size:
                        data += conn.recv(4096)
                        if key == ord("q"):
                            print("Socket closed.")
                            break
                    packed_msg_size = data[:payload_size]
                    data = data[payload_size:]
                    msg_size = struct.unpack(">L", packed_msg_size)[0]
                    while len(data) < msg_size:
                        data += conn.recv(4096)
                        if key == ord("q"):
                            print("Socket closed.")
                            break
                    frame_data = data[:msg_size]
                    data = data[msg_size:]

                    frame=pickle.loads(frame_data, fix_imports=True, encoding="bytes")
                    frame = cv2.imdecode(frame, cv2.IMREAD_COLOR)
                    cv2.imshow('ImageWindow',frame)
                    cv2.waitKey(1)
                    if key == ord("q"):
                        print("Socket closed.")
                        break
                except:
                    cv2.destroyAllWindows()
                    break

        s.shutdown(socket.SHUT_WR)
        s.close()
    if __name__ == "__main__":
        main()

    #client.py

    import socket
    import cv2
    import pickle
    import struct
    def main():
        encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 90]
        with socket.socket(socket.AF_INET,socket.SOCK_STREAM) as client_socket:
            print('Connecting to socket.')
            client_socket.connect((ENTER IP HERE, 12397))
            connection = client_socket.makefile('wb')
            print('Starting stream.')
            cam = cv2.VideoCapture(0)
            cam.set(3, 320*2);
            cam.set(4, 240*2);
            frame_time = int((1.0 / 30.0) * 1000.0)
            img_counter = 0
            while True:
                try:
                    ret, frame = cam.read()
                    if ret:
                        result, frame = cv2.imencode('.jpg', frame, encode_param)
                        data = pickle.dumps(frame, 0)
                        size = len(data)
                        client_socket.sendall(struct.pack(">L", size) + data)
                        img_counter += 1
                        if cv2.waitKey(frame_time) & 0xFF == ord('q'):
                            break
                    else:
                        break
                except KeyboardInterrupt:
                    break
        cam.release()
        client_socket.shutdown(socket.SHUT_WR)
        client_socket.close()
    if __name__ == "__main__":
        main()

Я хочу закрыть соединение, нажав q. В настоящее время я получаю WinErrors на сервере OSError: [WinError 10038] Была предпринята попытка выполнить операцию на чем-то, что не является сокетом ина клиенте ConnectionResetError: [WinError 10054] Существующее соединение было принудительно закрыто удаленным хостом, когда я (спам) "q" на стороне сервера, похоже, не ловит, если я просто нажму его один раз.

1 Ответ

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

Эта ошибка обычно возникает, если вы используете сокет после , когда вы его закрыли.

Теперь, если мы берем ваш сервер, вы делаете что-то вроде

with socket.socket(socket.AF_INET,socket.SOCK_STREAM) as s:
    ... code here ...

s.shutdown(socket.SHUT_WR)
s.close()

Это означает, что вызовы shutdown и close выполняются после сокета уже закрыты.

У вас такая же проблема в клиентской программе.

...