-
Задача такая: получить запрос, обработать его (сформировать ответ), отправить запросившему хосту на тотже порт ответ. Упрощенно код выглядит так: ...
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] ответ слишком большой?
-
Нет в TCP никаких пакетов, это поточный протокол !
А для отладки на сессионном и прикладном уровне (SIP - это прикладной уровень) никакие вайшарки нафих не нужны.
-
Я неточно выразился, не пакеты а фреймы (кадры) имелись ввиду, в которых на сколько я понимаю перрадаются содержимое потока...
Есть аналогичная прогрмма, которую я также отслеживаю wireshark'ом, она отправляет тотже самый ответ и wireshark нормально его анализирует и не выдает никаких ошибок - значит моя программа как-то не так отправляет данные...
-
> не пакеты а фреймы (кадры)
Какое тебе дело до фреймов на сессионном и прикладном уровне ?
Фреймами занимаеся стек протоколов TCP/IP твоего хоста, и пусть себе занимается. Твое дело - правильно отправить и принять поток данных прикл.уровня, а как уж он там будет доставлен, какими пакетами-фреймами-маршрутами - тебя вообще это никак не касается.
Если после успешного выполнения строки Socket.SendStream(Stream); условие Stream.Position = Stream.Size истинно, то считай что сервер выполнил свою миссию - передал принимающей стороне содержимое указанного тобой стрима.
-
модифицировал процедуру отправки следующим образом: 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 после обработки...
-
> B Memo1
Ты опять в доп.потоке лезешь в VCL ?
Ну недопустимо это, понимаешь ? Уже было ведь заострено твое внимание на это в предыдущей ветке на эту же тему, что не понятно ?
> пременная Stream не уничтожилась, по справке метод SendStream > убивает Stream после обработки
Нет такого в справке к TBaseSocket.Sendstream, не выдумывай.
-
> Ты опять в доп.потоке лезешь в VCL ?
кусок кода в который я привожу отдельный модуль в котором нет ничего VCL, приведенный код исправлен чтобы показать саму суть. Для ясности дела: в отдельном модуле я создаю не VCL компонент, который создает TTcpServer и с ним работает. Из основной формы динамически создается компонет из упомянутого отдельного модуля.
-
Вообще я правильно отвечаю в сокет из которого получил запрос? Правильно ли я оргпнизовал цыкл получения данных или как только данные во входном буфере закончились надо выходить из цыкла и далее...
-
Я не знаю что и где ты там создаешь, но при BlockMode = bmThreadBlocking обращения к Memo в обрабочике OnAccept недопустимы, потому что тело обработчика исполняется в доп.потоке.
Сколько раз это еще нужно объяснять ?
-
т.е. каждый раз когда возникает 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 который в главной форме естественно уже вывод в Мемо - также можно?
-
Вот схема:
while not Terminated and ClientSocket.Connected do begin .. цикл для чтения всего запроса .. .. формирование ответа на запрос.. .. оправка сформированного ответа .. end;
> цыкл
цыган, цыпленок, цыпочки - в "великом и могучем" всего три исключения из правил)
-
Вроде разобрался, были ошибки в ответе, сейчас все работает, т.е. мое приложение принимает сообщения от сервера и оправляет ответ, который успешно принимается сервером, но все-таки, я понимаю что транспортный уровень передачи данных меня совсем не должен интересовать но не пойму почему wireshark так реагирует на оправляемые данные, от других программ работающих с SIP протоколом такого не наблюдается (при отправке ими аналогичных ответов) - значит ли это что отправка данных до конца правилно не реализована?
-
Сформированный ответ должен отправляться в соект из которого был получен запрос или для отправки ответа требуется отдельный TcpClient которым надо подсоединяться к сокету из котороко получен запрос и им отправлять ответ?
-
> мое приложение принимает сообщения от сервера и оправляет > ответ, который успешно принимается сервером
Ты не понимаешь что творишь.
Твое приложение в этой его функциональной части является TCP-сервером.
В TCP всегда одна сторона - сервер, другая сторона - клиент. Как минимум на этапе установления соединения, о коем ты и ведешь речь, упоминая OnAccept-событие.
> почему wireshark так реагирует на оправляемые данные
Я не знаю что это за зверь - wireshark, - но советую тебе при текущем уровне твоих знаний забыть его как страшный сон.
Уверяю тебя - он тебе нахрен не нужен)
> Сформированный ответ должен отправляться в соект из которого > был получен запрос
Да.
> или для отправки ответа требуется отдельный TcpClient которым > надо подсоединяться к сокету из котороко получен запрос
Тебе выдадут шнобелевскую премию, если ты умудришься и продемонстрируешь это в своем коде, вопреки всем существующим стандартам)
|