Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2011.03.20;
Скачать: [xml.tar.bz2];

Вниз

TTcpServer: Ответ на запрос - что не так?   Найти похожие ветки 

 
d@vinchi ©   (2009-02-27 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]


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


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

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

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


 
d@vinchi ©   (2009-02-27 14:11) [2]

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

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


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


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


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

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

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


 
d@vinchi ©   (2009-02-27 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 после обработки...


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


> B Memo1


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

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


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


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


 
d@vinchi ©   (2009-02-27 15:12) [6]


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

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


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

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


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

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

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


 
d@vinchi ©   (2009-02-27 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 который в главной форме естественно уже вывод в Мемо - также можно?


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

Вот схема:

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


> цыкл


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


 
d@vinchi ©   (2009-02-27 17:23) [11]

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


 
d@vinchi ©   (2009-02-27 17:58) [12]

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


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


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


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

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

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


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


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

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


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


Да.


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


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



Страницы: 1 вся ветка

Форум: "Сети";
Текущий архив: 2011.03.20;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.006 c
15-1291618037
TUser
2010-12-06 09:47
2011.03.20
1994 - год открытия численного интегрирования


15-1291861735
Арт
2010-12-09 05:28
2011.03.20
Драйвер аудио...


15-1291657885
Училка
2010-12-06 20:51
2011.03.20
Как вам такая идея насчет inline дерективы


15-1291536797
oxffff
2010-12-05 11:13
2011.03.20
Доступны ли Вам блоги на blogspot.com?


2-1293439574
NanoTek
2010-12-27 11:46
2011.03.20
Поменять шрифт Редактора кода





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский