На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Соблюдайте общие правила форума
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Указывайте точные версии Delphi и используемых сетевых библиотек.

Не приветствуется поднятие старых тем. Если ваш вопрос перекликается со старой темой, то для вопроса лучше создать новую тему, а старую указать в первом сообщении с описанием взаимосвязи.

Внимание:
попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...

Полезные ссылки:
user posted image MSDN Library user posted image FAQ раздела user posted image Поиск по разделу user posted image Как правильно задавать вопросы


Выразить свое отношение к модераторам раздела можно здесь: user posted image Krid, user posted image Rouse_

Модераторы: Krid, Rouse_
Страницы: (3) [1] 2 3  все  ( Перейти к последнему сообщению )  
> интерфейс RTSP(554)
    всем привет!

    надо сделать интерфейс общения с IP камерой, через RTSP
    уже нашёл описание данного стандарта (правда на английском, но это не проблема)

    на данный момент не получается правильно последовательно считать данные с камеры

    отправляю запрос:
    ExpandedWrap disabled
      'DESCRIBE rtsp://admin:admin@10.10.10.64:554/ RTSP/1.0' + #13#10 +
      'CSeq: 2' + #13#10 +
      'User-Agent: AppName' + #13#10 +
      'Accept: application/sdp' + #13#10;


    назад получаю не полные данные, что именно я должен получить я знаю, но вот приходят они частично обрезанные

    получилось считать целиком при помощи IdTCPClient
    но второй запрос уже обрабатываться не хочет, т.е. отсылаю его, а мне в ответ ошибка 10054

    подскажите как правильно отправить/получить данные

    P.S. разве в нет в дельфи аналогов функций SEND, RECV и обязательно надо использовать подключение заголовочного файла из "си"
    Сообщение отредактировано: woojin -
      Все есть, и recv, и классовые обертки. Но если уровень познаний в сокетах невелик, то легче использовать Indy.
      Обрезанные данные - скорее всего потому, что вычитываешь не полностью.
        да, уровень знаний равен НУЛЮ (((
        понятно что не полностью читается, но в "индях" первый пакет данных читается полностью, а вот при отправке запроса на второй пакет, вылетает ошибка - почему инди не правильно работает, если там всё "оптимизировано и настроено"?
          Цитата Fr0sT @
          Все есть, и recv, и классовые обертки.

          а где именно есть?
          и что за обёртка - win.sockets и TBaseSocket?
            Почему сервер рвет связь - это уж неизвестно. Возможно, ты ему что-то не то скармливаешь. Можешь попробовать отправлять запросы вручную через telnet - вот уж там точно влияние надстроек исключено. Ну а неполное вычитывание, не имея кода, точно никак не проверишь.
            Цитата woojin @
            а где именно есть?
            и что за обёртка - win.sockets и TBaseSocket?

            WinSock, TSocketClient
              ExpandedWrap disabled
                procedure TForm1.Button3Click(Sender: TObject);
                var
                  request: TRequest;
                  cmd, h, c: string;
                  szh, szc: integer;
                 
                begin
                  cmd := 'DESCRIBE rtsp://admin:admin@10.10.10.64:554/ RTSP/1.0' + #13#10 +
                         'CSeq: 2' + #13#10 +
                         'User-Agent: AppName' + #13#10 +
                         'Accept: application/sdp' + #13#10;
                 
                  TcpClient1.Open;
                  TcpClient1.Active:=True;
                  TcpClient1.Sendln(cmd);
                //  TcpClient1.Receiveln;
                end;
                 
                procedure TForm1.TcpClient1Receive(Sender: TObject; Buf: PAnsiChar;
                  var DataLen: Integer);
                begin
                  Memo1.Lines.Add('Receive(' + IntToStr(DataLen) + '): ' + Buf);
                end;


              вот таким кодом отправляю запрос, но в ответ ни чего не получаю без закомментированной строки
              если её раскоментировать, то в Memo сразу появляется текст
              ExpandedWrap disabled
                RTSP/1.0 200 OK
                CSeq: 2
                Content-Type: application/sdp
                Content-Base: rtsp://10.10.10.64:554/
                Content-Length: 545
                 
                v=0
                o=- 1480520940099739 1480520940099739 IN IP4 10.10.10.64
                s=Media Presentation
                e=NONE
                b=AS:5050
                t=0 0
                a=control:rtsp://10.10.10.64:554/
                m=video 0 RTP/AVP 96
                c=IN IP4 0.0.0.0
                b=AS:5000
                a=recvonly
                a=x-dimensions:1280,720
                a=control:rtsp://10.10.10.64:554/trackID=1
                a=rtpmap:96 H264/90000
                a=fmtp:96 profile-level-id=420029; packetization-mode=1; sprop-parameter-sets=Z0IAII2NQCgC3QgAADhAAAr8gCA=,aM44gA==
                a=Media_header:


              но он не полный!
              не хватает в конце (после двоеточия)
              ExpandedWrap disabled
                MEDIAINFO=494D4B48010100000400010000000000000000000000000000000000000000000000000000000000;
                a=appversion:1.0
              Сообщение отредактировано: woojin -
                Что такое TcpClient? Он синхронный или асинхронный? Что за партизаны, каждый кусок инфы клещами тянуть приходится...

                Не знаю, как там у RTSP, но у HTTP по стандарту запрос должен завершаться двумя \r\n
                  Цитата Fr0sT @
                  Что такое TcpClient?

                  у RAD STUDIO XE5 есть набор компонентов INTENET, это оттуда
                  Цитата Fr0sT @
                  запрос должен завершаться двумя \r\n

                  это \r\n\r\n?
                    Цитата woojin @
                    это \r\n\r\n?

                    Ага.
                      сделал на другом компоненте
                      вроде как получилось, с одним "НО" ни как не могу понять, как подцепится к видео потоку
                      ExpandedWrap disabled
                        var                  
                          session: string;   // глобальная переменная
                         
                        // получаю данные с камеры
                        procedure TForm1.ButtonDescrClick(Sender: TObject);
                        var
                          s: string;
                         
                        begin
                          s := 'DESCRIBE rtsp://admin:admin@10.10.10.64:554 RTSP/1.0'+#13#10+
                               'CSeq: 2'+#13#10+
                               'User-Agent: AppName'+#13#10+
                               'Accept: application/sdp'+#13#10;
                         
                          if ClientSocket1.Socket.Connected then
                            begin
                              ClientSocket1.Socket.Close;
                              ClientSocket1.Close;
                            end;
                          ClientSocket1.Port := 554;
                          ClientSocket1.Address := '10.10.10.64';
                          ClientSocket1.ClientType := TClientType(ComboBox1.ItemIndex); // ctNonBlocking или ctBlocking - без разницы работает одинаково
                          ClientSocket1.Open;
                        end;

                      ответ
                      ExpandedWrap disabled
                        RTSP/1.0 200 OK
                        CSeq: 2
                        Content-Type: application/sdp
                        Content-Base: rtsp://admin:admin@10.10.10.64:554/
                        Content-Length: 575
                         
                        v=0
                        o=- 1481815230001505 1481815230001505 IN IP4 10.10.10.64
                        s=Media Presentation
                        e=NONE
                        b=AS:5050
                        t=0 0
                        a=control:rtsp://admin:admin@10.10.10.64:554/
                        m=video 0 RTP/AVP 96
                        c=IN IP4 0.0.0.0
                        b=AS:5000
                        a=recvonly
                        a=x-dimensions:1280,720
                        a=control:rtsp://admin:admin@10.10.10.64:554/trackID=1
                        a=rtpmap:96 H264/90000
                        a=fmtp:96 profile-level-id=420029; packetization-mode=1; sprop-parameter-sets=Z0IAII2NQCgC3QgAADhAAAr8gCA=,aM44gA==
                        a=Media_header:MEDIAINFO=494D4B48010100000400010000000000000000000000000000000000000000000000000000000000;
                        a=appversion:1.0

                      ExpandedWrap disabled
                        // делаю настройки
                        procedure TForm1.ButtonSetupClick(Sender: TObject);
                        var
                          s: string;
                          start, finish: integer;
                         
                        begin
                          s := 'SETUP rtsp://admin:admin@10.10.10.64:554/trackID=1 RTSP/1.0'+#13#10+
                               'CSeq: 3'+#13#10+
                               'User-Agent: AppName'+#13#10+
                               'Transport: RTP/AVP;unicast;client_port=10024-10025'+#13#10+#13#10; // порты взяты на обум но они свободны
                         
                          ClientSocket1.Socket.SendText(s);
                          sleep(300);
                          s := ClientSocket1.Socket.ReceiveText;
                          start := pos('Session:', s)+Length('Session:');   // \
                          finish := pos(';', s, start);                     //  > получаю номер сессии в глобальную переменную session
                          session := trim(copy(s, start, finish-start));    // /
                          Memo1.Lines.Add(s);
                        end;

                      ответ
                      ExpandedWrap disabled
                        RTSP/1.0 200 OK
                        CSeq: 3
                        Session:       1471661481;timeout=60
                        Transport: RTP/AVP;unicast;client_port=10024-10025;server_port=8280-8281;ssrc=509cf2f0;mode="play"
                        Date:  Thu, Dec 15 2016 15:20:30 GMT

                      ExpandedWrap disabled
                        // отправляю запрос на проигрывание
                        procedure TForm1.ButtonPlayClick(Sender: TObject);
                        var
                          s: string;
                         
                        begin
                          s := 'PLAY rtsp://admin:admin@10.10.10.64:554/ RTSP/1.0'+#13#10+
                               'CSeq: 4'+#13#10+
                               'User-Agent: AppName'+#13#10+
                               'Session: '+ session +#13#10+
                               'Range: npt=0.000-'+#13#10+#13#10;
                         
                          ClientSocket1.Socket.SendText(s);
                          sleep(300);
                          s := ClientSocket1.Socket.ReceiveText;
                          Memo1.Lines.Add(s);
                        end;

                      ответ
                      ExpandedWrap disabled
                        RTSP/1.0 200 OK
                        CSeq: 4
                        Session:       1471661481
                        RTP-Info: url=rtsp://admin:admin@10.10.10.64:554/trackID=1;seq=49912;rtptime=665131904
                        Date:  Thu, Dec 15 2016 15:20:30 GMT

                      и далее как то надо начать читать поток... но вот как не могу разобраться, т.е. как назначить своему клиенту именно те порты которые я указал выше (10024-10025) и что именно надо писать после внесения данных в лог (Memo1.Lines.Add(s);) что бы началось чтение из указанных портов сервера?
                      надо ли создавать новы(й/е) компонент(ы) TClientSocket с разными портами сервера (опять же вопрос как назначить свои собственные порты)?

                      в логе програмки на С++ вот что отображается (часть с предыдущего ответа):
                      ExpandedWrap disabled
                        Date:  Thu, Dec 15 2016 15:20:30 GMT
                         
                         
                        [URL:"rtsp://admin:admin@10.10.10.64:554/"]: Started playing session...
                        Stream "rtsp://admin:admin@10.10.10.64:554/"; video/H264:    Received 20 bytes.      Presentation time: 1481797230.432135!
                        Stream "rtsp://admin:admin@10.10.10.64:554/"; video/H264:    Received 4 bytes.       Presentation time: 1481797230.432135!
                        Stream "rtsp://admin:admin@10.10.10.64:554/"; video/H264:    Received 25377 bytes.   Presentation time: 1481797230.432135!
                        Stream "rtsp://admin:admin@10.10.10.64:554/"; video/H264:    Received 3025 bytes.    Presentation time: 1481797230.472135!
                        Stream "rtsp://admin:admin@10.10.10.64:554/"; video/H264:    Received 3041 bytes.    Presentation time: 1481797230.512135!


                      если кто то занимался подобными вещами посоветуйте плиз
                        Если надо слушать порт на своей машине, чтобы сервер на него начал передавать поток, то это Bind на порт, Listen, Accept, получение принимающего сокета и затем чтение из него. Если же надо инициировать соединение самому, то это проще - просто еще один clientsocket.
                        А вообще советую почитать статью А. Григорьева про сокеты, чтобы иметь представление о предмете. Потому что "ctNonBlocking или ctBlocking - без разницы работает одинаково", "sleep(300);" - это тихий ужас. Кроме того, если ответ сервера не уместится в один пакет, то ReceiveText вернет только часть ответа. Надо собирать ответ в буфере, пока не встретится сигнатура завершения, и тогда уже его разбирать.
                          Цитата Fr0sT @
                          "ctNonBlocking или ctBlocking - без разницы работает одинаково"

                          по поводу этого, мне просто не понятно в каком случае применить блокировку
                          Цитата Fr0sT @
                          ReceiveText вернет только часть ответа

                          ползал я в System.Win.ScktComp эта функция (на сколько я понимаю, хотя могу и ошибаться) читает полностью весь пакет
                          ExpandedWrap disabled
                            function TCustomWinSocket.ReceiveText: AnsiString;
                            begin
                              SetLength(Result, ReceiveBuf(Pointer(nil)^, -1));                // выставляет длину получаемых данных
                              SetLength(Result, ReceiveBuf(Pointer(Result)^, Length(Result))); // и тут уже записывает их в Result
                            end;

                          а вот без этого
                          Цитата Fr0sT @
                          "sleep(300);"

                          вообще читать ни чего не хочет, кстати интересно что если поставить меньше 300 то тоже ни каких данных не приходит
                          если использовать OnRead снова ни чего нет, я так понял что надо самому инициализировать чтение потока, по этому сначала отправка сообщения, потом задержка и чтение

                          P.S. статейка эта Статья :: 2.2. Сокеты Windows : А Григорьев? правильно нашёл?
                          и ещё Bind, Listen, Accept - их можно задать у ClientSocket или придётся всё самому описывать с использованием WinApi.WinSock?
                            Цитата woojin @
                            по поводу этого, мне просто не понятно в каком случае применить блокировку

                            Блокировка блокирует выполнение, если в данный момент не получается выполнить функцию прямо сейчас. Т.е. вокруг неблокирующего сокета должна быть обвязка, тем или иным способом повторяющая вызов либо проверяющая результат. В твоем случае легче блокирующий.
                            Цитата woojin @
                            ползал я в System.Win.ScktComp эта функция (на сколько я понимаю, хотя могу и ошибаться) читает полностью весь пакет

                            Да, пакет читает. Но что если ответ сервера в него не влезет? Функция прочитает только часть. Т.ч. в идеале надо склеивать в накопитель, искать там \r\n\r\n (конец заголовка), разбирать его, вычленять content-length и считывать тело ответа, если он есть.
                            Цитата woojin @
                            вообще читать ни чего не хочет, кстати интересно что если поставить меньше 300 то тоже ни каких данных не приходит
                            если использовать OnRead снова ни чего нет, я так понял что надо самому инициализировать чтение потока, по этому сначала отправка сообщения, потом задержка и чтение

                            При блокирующем режиме должен читать без всяких слипов.
                            Цитата woojin @
                            P.S. статейка эта Статья :: 2.2. Сокеты Windows : А Григорьев? правильно нашёл?

                            Почти, только в WSA не стоит лезть, можно обойтись берклевскими функциями.
                            Цитата woojin @
                            и ещё Bind, Listen, Accept - их можно задать у ClientSocket или придётся всё самому описывать с использованием WinApi.WinSock?

                            Насколько я помню, нужен ServerSocket. Но я не знаю, как используется этот порт - клиент у себя открывает или сервер.
                              Цитата Fr0sT @
                              При блокирующем режиме должен читать без всяких слипов.

                              подцепляюсь с блокировкой (кнопка DESCR) - ни какого ответа пока не нажмёшь на кнопку SETUP - после приходит первый ответ :( (фигня какая то)
                              Цитата Fr0sT @
                              Функция прочитает только часть

                              там нет ограничений на количество прочитанного (о чём говорит параметр -1 SetLength(Result, ReceiveBuf(Pointer(nil)^, -1)))
                              Цитата Fr0sT @
                              можно обойтись берклевскими функциями.

                              примерчик можно?
                              Цитата Fr0sT @
                              Насколько я помню, нужен ServerSocket. Но я не знаю, как используется этот порт - клиент у себя открывает или сервер.

                              это получается сервер к серверу будет цепляться?
                              есть пример? (если не сложно)

                              P.S. могу дать С++ программу (она правда под FreeBSD) там (для меня) дикий сумбур, но хотелось бы сделать нечто подобное
                                Цитата woojin @
                                подцепляюсь с блокировкой (кнопка DESCR) - ни какого ответа пока не нажмёшь на кнопку SETUP - после приходит первый ответ

                                А какой может быть ответ, если в Descr ты ничего серверу не отсылаешь?
                                Цитата woojin @
                                там нет ограничений на количество прочитанного (о чём говорит параметр -1 SetLength(Result, ReceiveBuf(Pointer(nil)^, -1)))

                                там нет ограничений на количество прочитанного на момент вызова функции.
                                1. Пришел пакет с Response pt1
                                2. Socket.Read
                                3. Пришел пакет с Response pt2
                                4. ???
                                Цитата woojin @
                                примерчик можно?

                                Это обычные функции/методы без WSA. recv, send, connect и т.д. См. первую часть статьи Григорьева.
                                Цитата woojin @
                                это получается сервер к серверу будет цепляться?

                                Повторяю: я не знаю, как устроен протокол. Смотри в спеки, как там эти порты будут использоваться. Если смущает название "сервер" - окей, пусть это будет "слушающий сокет на клиенте". Но компонент все равно называется ServerSocket.
                                Цитата woojin @
                                могу дать С++ программу (она правда под FreeBSD) там (для меня) дикий сумбур, но хотелось бы сделать нечто подобное

                                Давай
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (3) [1] 2 3  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0711 ]   [ 17 queries used ]   [ Generated: 28.03.24, 10:30 GMT ]