![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
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 - это прикладной уровень) никакие вайшарки нафих не нужны.