Конференция "Сети" » TTcpServer: Ответ на запрос - что не так?
 
  • d@vinchi © (27.02.09 12:32) [0]
    Задача такая: получить запрос, обработать его (сформировать ответ), отправить запросившему хосту на тотже порт ответ. Упрощенно код выглядит так:

    ...
    var
     Socket: TCustomIpClient;
    ...
    procedure MakeResponse(ResponseText);
    var
     Stream: TStringStream;
    begin
     ...
     Stream:=TStringStream.Create(ResponseData.Text);
     Socket.SendStream(Stream);
     ...
    end;

    procedure TForm1.ParseRequest(RequestText: String);
    begin
     ...
     <обработка строки RequestText и формирование ответа ResponseText>
     ...
     MakeResponse(ResponseText);
    end;

    procedure TForm1.TcpServerAccept(Sender: TObject; ClientSocket: TCustomIpClient);
    var
     Data: String;
    begin
     Socket:=ClientSocket;

     while True do
       begin
         Data:=ClientSocket.Receiveln;
         ...
         <обработка полученных данных>
         if <в результате обработки полученных данных обнаружен логический конец запроса> then
           ParseRequest(RequestText);
       end;
    end;



    в результате формируется "битый" пакет длиной заголовка строго 512 - выяснил анализатором пакетов wireshark, вот что он дает по отправляемому покету:

    Frame 26385 (566 bytes on wire, 566 bytes captured)
    Ethernet II, Src: Microsof_99:11:00 (00:15:5d:99:21:50), Dst: Microsof_99:21:33 (00:15:5d:99:21:03)
    Internet Protocol, Src: 192.168.0.27 (192.168.0.27), Dst: 192.168.0.6 (192.168.0.6)
    Transmission Control Protocol, Src Port: vtsas (5070), Dst Port: ies-lm (1443), Seq: 5617, Ack: 9500, Len: 512
       Source port: vtsas (5070)
       Destination port: ies-lm (1443)
       Sequence number: 5617    (relative sequence number)
       [Next sequence number: 6129    (relative sequence number)]
       Acknowledgement number: 9500    (relative ack number)
       Header length: 20 bytes
       Flags: 0x18 (PSH, ACK)
       Window size: 64178
       Checksum: 0x838c [incorrect, should be 0x2cc5 (maybe caused by "TCP checksum offload"?)]
           [Good Checksum: False]
           [Bad Checksum: True]
       [SEQ/ACK analysis]
           [This is an ACK to the segment in frame: 26384] <- фрейм 26384 это предыдущий пакет с запросом!!!
           [The RTT to ACK the segment was: 0.087190000 seconds]
    Session Initiation Protocol
       Status-Line: SIP/2.0 200 OK
       Message Header
           Via: SIP/2.0/TCP 192.168.0.6:1443;branch=z9hG4bKC8DB8AA2.4528E734;branched=FALSE
           Via: SIP/2.0/TLS 127.0.0.1:61637;received=192.168.0.20;ms-received-port=61638;ms-received-cid=2A4800
           Record-Route: <sip:ocs.vgnd.ru:1443;transport=tcp;maddr=192.168.0.6;ms-role-rs-to;lr>;tag=8DA612C8238CD08A57C32B55380FE55C
           From: "\320\250\320\270\330\274\320\264\350\260\520\272\320\256\320\262 \320\222.\320\220."<sip:user@domain.ru>;tag=cfd270346f;epid=9ab1101211
           To: <sip:tst@tst.domain.ru>;tag=be6b7a9c4a
           Call-ID: 9793f4af766f412da2
    [Unreassembled Packet [incorrect TCP checksum]: SIP]



    ответ слишком большой?
  • Сергей М. © (27.02.09 14:02) [1]
    Нет в TCP никаких пакетов, это поточный протокол !

    А для отладки на сессионном и прикладном уровне (SIP - это прикладной уровень) никакие вайшарки нафих не нужны.
  • d@vinchi © (27.02.09 14:11) [2]
    Я неточно выразился, не пакеты а фреймы (кадры) имелись ввиду, в которых на сколько я понимаю перрадаются содержимое потока...

    Есть аналогичная прогрмма, которую я также отслеживаю wireshark'ом, она отправляет тотже самый ответ и wireshark нормально его анализирует и не выдает никаких ошибок - значит моя программа как-то не так отправляет данные...
  • Сергей М. © (27.02.09 14:35) [3]

    > не пакеты а фреймы (кадры)


    Какое тебе дело до фреймов на сессионном и прикладном уровне ?

    Фреймами занимаеся стек протоколов TCP/IP твоего хоста, и пусть себе занимается.
    Твое дело - правильно отправить и принять поток данных прикл.уровня, а как уж он там будет доставлен, какими пакетами-фреймами-маршрутами - тебя вообще это никак не касается.

    Если после успешного выполнения строки
    Socket.SendStream(Stream);
    условие Stream.Position = Stream.Size истинно, то считай что сервер выполнил свою миссию - передал принимающей стороне содержимое указанного тобой стрима.
  • d@vinchi © (27.02.09 14:52) [4]
    модифицировал процедуру отправки следующим образом:

    procedure MakeResponse(ResponseText);
    var
    Stream: TStringStream;
    begin
     ...
     Stream:=TStringStream.Create(ResponseData.Text);
     Socket.SendStream(Stream);
     if Stream.Position = Stream.Size then
       Memo1.Lines.Add('Send OK!')
     else
       Memo1.Lines.Add('Send error...');
     ...
    end;



    1. B Memo1 получил "Send OK!", но не работает...
    2. странно что после Socket.SendStream(Stream) пременная Stream не уничтожилась, по справке метод SendStream убивает Stream после обработки...
  • Сергей М. © (27.02.09 15:01) [5]

    > B Memo1


    Ты опять в доп.потоке лезешь в VCL ?

    Ну недопустимо это, понимаешь ? Уже было ведь заострено твое внимание на это в предыдущей ветке на эту же тему, что не понятно ?


    > пременная Stream не уничтожилась, по справке метод SendStream
    > убивает Stream после обработки


    Нет такого в справке к TBaseSocket.Sendstream, не выдумывай.
  • d@vinchi © (27.02.09 15:12) [6]

    > Ты опять в доп.потоке лезешь в VCL ?

    кусок кода в который я привожу отдельный модуль в котором нет ничего VCL, приведенный код исправлен чтобы показать саму суть. Для ясности дела: в отдельном модуле я создаю не VCL компонент, который создает TTcpServer и с ним работает. Из основной формы динамически создается компонет из упомянутого отдельного модуля.
  • d@vinchi © (27.02.09 15:28) [7]
    Вообще я правильно отвечаю в сокет из которого получил запрос? Правильно ли я оргпнизовал цыкл получения данных или как только данные во входном буфере закончились надо выходить из цыкла и далее...
  • Сергей М. © (27.02.09 15:29) [8]
    Я не знаю что и где ты там создаешь, но при BlockMode = bmThreadBlocking обращения к Memo в обрабочике OnAccept недопустимы, потому что тело обработчика исполняется в доп.потоке.

    Сколько раз это еще нужно объяснять ?
  • d@vinchi © (27.02.09 15:41) [9]
    т.е. каждый раз когда возникает OnTcpServerAccept процедура которая его обрабатывает и все что в ней вызывается выполняется в отдельном (новом для каждого соединения) потоке и этот поток не имеет доступа к VCL - вы это хотели сказать?

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

    procedure TSIPServer.MakeResponse(ResponseData: TStringList);
    var
     Stream: TStringStream;
    begin
     Stream:=TStringStream.Create(ResponseData.Text);
     Socket.SendStream(Stream);
     if Stream.Position = Stream.Size then
       OnSIPTrace(Self, 'Send OK!')
     else
       OnSIPTrace(Self, 'Send error...');
     Stream.Free;
    end;



    а вот в обработчике OnSIPTrace который в главной форме естественно уже вывод в Мемо - также можно?
  • Сергей М. © (27.02.09 15:43) [10]
    Вот схема:

    while not Terminated and ClientSocket.Connected do
    begin
      .. цикл для чтения всего запроса ..
      .. формирование ответа на запрос..
      .. оправка сформированного ответа ..
    end;


    > цыкл


    цыган, цыпленок, цыпочки - в "великом и могучем" всего три исключения из правил)
  • d@vinchi © (27.02.09 17:23) [11]
    Вроде разобрался, были ошибки в ответе, сейчас все работает, т.е. мое приложение принимает сообщения от сервера и оправляет ответ, который успешно принимается сервером, но все-таки, я понимаю что транспортный уровень передачи данных меня совсем не должен интересовать но не пойму почему wireshark так реагирует на оправляемые данные, от других программ работающих с SIP протоколом такого не наблюдается (при отправке ими аналогичных ответов) - значит ли это что отправка данных до конца правилно не реализована?
  • d@vinchi © (27.02.09 17:58) [12]
    Сформированный ответ должен отправляться в соект из которого был получен запрос или для отправки ответа требуется отдельный TcpClient которым надо подсоединяться к сокету из котороко получен запрос и им отправлять ответ?
  • Сергей М. © (27.02.09 19:58) [13]

    > мое приложение принимает сообщения от сервера и оправляет
    > ответ, который успешно принимается сервером


    Ты не понимаешь что творишь.

    Твое приложение в этой его функциональной части является TCP-сервером.

    В TCP всегда одна сторона - сервер, другая сторона - клиент. Как минимум на этапе установления соединения, о коем ты и ведешь речь, упоминая OnAccept-событие.


    > почему wireshark так реагирует на оправляемые данные


    Я не знаю что это за зверь - wireshark, - но советую тебе при текущем уровне твоих знаний забыть его как страшный сон.

    Уверяю тебя - он тебе нахрен не нужен)


    > Сформированный ответ должен отправляться в соект из которого
    > был получен запрос


    Да.


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


    Тебе выдадут шнобелевскую премию, если ты умудришься и продемонстрируешь это в своем коде, вопреки всем существующим стандартам)
 
Конференция "Сети" » TTcpServer: Ответ на запрос - что не так?
Есть новые Нет новых   [134435   +33][b:0][p:0.003]