Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

TTcpServer: Ответ на запрос - что не так?


d@vinchi ©   (2009-02-27 12:32:00) 

Задача такая: получить запрос, обработать его (сформировать ответ), отправить запросившему хосту на тотже порт ответ. Упрощенно код выглядит так:

...
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]


ответ слишком большой?


Сергей М.   (2009-02-27 19:58:00) [1]


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


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

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

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


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


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

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


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


Да.


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


Тебе выдадут шнобелевскую премию, если ты умудришься и продемонстрируешь это в своем коде, вопреки всем существующим стандартам)


d@vinchi   (2009-02-27 17:58:00) [2]

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


d@vinchi   (2009-02-27 17:23:00) [3]

Вроде разобрался, были ошибки в ответе, сейчас все работает, т.е. мое приложение принимает сообщения от сервера и оправляет ответ, который успешно принимается сервером, но все-таки, я понимаю что транспортный уровень передачи данных меня совсем не должен интересовать но не пойму почему wireshark так реагирует на оправляемые данные, от других программ работающих с SIP протоколом такого не наблюдается (при отправке ими аналогичных ответов) - значит ли это что отправка данных до конца правилно не реализована?


Сергей М.   (2009-02-27 15:43:00) [4]

Вот схема:

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


> цыкл


ц ыган, ц ыпленок, ц ыпочки - в "великом и могучем" всего триисключения из правил)


d@vinchi   (2009-02-27 15:41:00) [5]

т.е. каждый раз когда возникает 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 который в главной форме естественно уже вывод в Мемо - также можно?


Сергей М.   (2009-02-27 15:29:00) [6]

Я не знаю что и где ты там создаешь, но при BlockMode = bmThreadBlocking обращения к Memo в обрабочике OnAccept недопустимы, потому что тело обработчика исполняется в доп.потоке.

Сколько раз это еще нужно объяснять ?


d@vinchi   (2009-02-27 15:28:00) [7]

Вообще я правильно отвечаю в сокет из которого получил запрос? Правильно ли я оргпнизовал цыкл получения данных или как только данные во входном буфере закончились надо выходить из цыкла и далее...


d@vinchi   (2009-02-27 15:12:00) [8]


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

кусок кода в который я привожу отдельный модуль в котором нет ничего VCL, приведенный код исправлен чтобы показать саму суть. Для ясности дела: в отдельном модуле я создаю не VCL компонент, который создает TTcpServer и с ним работает. Из основной формы динамически создается компонет из упомянутого отдельного модуля.


Сергей М.   (2009-02-27 15:01:00) [9]


> B Memo1


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

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


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


Нет такого в справке к TBaseSocket.Sendstream, не выдумывай.


d@vinchi   (2009-02-27 14:52:00) [10]

модифицировал процедуру отправки следующим образом:

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 после обработки...


Сергей М.   (2009-02-27 14:35:00) [11]


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


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

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

Если после успешноговыполнения строки
Socket.SendStream(Stream);
условие Stream.Position = Stream.Size истинно, то считай что сервер выполнил свою миссию - передал принимающей стороне содержимое указанного тобой стрима.


d@vinchi   (2009-02-27 14:11:00) [12]

Я неточно выразился, не пакеты а фреймы (кадры) имелись ввиду, в которых на сколько я понимаю перрадаются содержимое потока...

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


Сергей М.   (2009-02-27 14:02:00) [13]

Нет в TCP никаких пакетов, это поточныйпротокол !

А для отладки на сессионном и прикладном уровне (SIP - это прикладной уровень) никакие вайшарки нафих не нужны.


Наверх

Титульная страница Поиск, карта сайта Написать письмо