Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2011.03.20;
Скачать: CL | DM;

Вниз

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;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.012 c
15-1291411776
Юрий
2010-12-04 00:29
2011.03.20
С днем рождения ! 4 декабря 2010 суббота


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


15-1291152578
Юрий
2010-12-01 00:29
2011.03.20
С днем рождения ! 1 декабря 2010 среда


2-1292942706
Gu
2010-12-21 17:45
2011.03.20
Ускорить прокрутку Listview


2-1293131507
nza
2010-12-23 22:11
2011.03.20
Как отлаживать компонент?