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

Вниз

Прокси-Сервер. Как закрыть соединение с браузером.   Найти похожие ветки 

 
SergP   (2003-08-13 18:16) [0]

Конектюсь браузером через мой прокси-сервер. Уже вроде бы все нормально. Но при загрузке сайта, страничка в браузере не отображается. Хотя в браузер загружается все как нужно. Когда я закрываю мой прокси, то в этот момент в браузере отображается все как нужно. Я так понимаю что после загрузки конкретного элемента странички нужно закрыть соответствующее сокетное соединение Tserversocket c браузером (прокси пишу с использованием Tserversocket и Tclientsocket).
Но вот проблема: как узнать когда нужно закрывать соединение?
Какое событие для этого использовать?
Думал что нужно для этого узнавать размер загружаемых данных, и после того как именно столько данных было получено конкретным соединением то закрывать его. Но ведь не всегда можно определить размер входящих данных.


 
nikkie   (2003-08-13 18:27) [1]

когда http сервер отсылает все данные, он закрывает соединение. ты узнаешь о том, что данных больше не будет, по событию OnDisconnect. отсылаешь все данные своему клиенту и после этого делаешь Disconnect сам.


 
SergP   (2003-08-13 19:22) [2]


> nikkie © (13.08.03 18:27) [1]
> когда http сервер отсылает все данные, он закрывает соединение.
> ты узнаешь о том, что данных больше не будет, по событию
> OnDisconnect. отсылаешь все данные своему клиенту и после
> этого делаешь Disconnect сам.


Ага. Кстати я не совсем понял. Ты хочешь сказать что при возникновении события OnDisconnect в Tclientsocket будут данные, которые нужно оттуда забрать, и которые там появились без возникновения события OnRead?

И еще. Есть такие ситуации. В серверном сокете возникает событие OnClientRead c SocketHandle допустим =64. Создаю и активирую для этого хендла клиентский сокет, и передаю ему данные (по соответствующему событию). клиентский сокет отправляет запрос дальше (в инет). Получает несколько пакетов данных (я их передаю в серверный сокет, после чего клиентский сокет дисконектится, но после этого в серверном сокете возникает событие OnClientRead с тем же самым хендлом. Что делать? снова активировать клиентский сокет?
И иногда бывает что клиентский сокет еще не дисконектился а с серверного снова поступают данные с тем же хендлом. Что тут делать? Передавать данные в клиентский сокет или сначала его насильно деактивировать, после чего вновь активировать и после того уже передавать данные?


 
SergP   (2003-08-13 20:50) [3]

Хм. Интерестная вещь. Когда дисконектится клиентский сокет, я дисконектю соответствующее соединение в серверном сокете. И тем не менее после окончания загрузки остаются активными некоторые из клиентских сокетов, но ни одного активного соединения в серверном сокете. Получается что некоторые из них сами дисконектились, но при этом я что-то не заметил чтобы генерировалось событие OnClientDisconnect в серверном сокете.
Это как понимать?


 
nikkie   (2003-08-13 20:55) [4]

>Ты хочешь сказать что ...
нее, я вообще ничего не хочу говорить про эти компоненты. просто я в них сам не уверен - если ты делаешь асинхронный Send, а потом Disconnect - можно ли быть уверенным, что все данные будут отправлены? сдается мне, что нет.

>SocketHandle допустим =64
зачем тебе на хендл смотреть - непонятно. работай с указателями на объекты. в событии OnClientConnect тебе передается Socket. Создаешь ClientSocket и ссылку на него сохраняешь в Socket.Data. в ClientSocket.Socket.Data сохраняешь ссылку на Socket. таким образом, при любом событии будешь знать куда писать.


 
SergP   (2003-08-13 21:31) [5]


> зачем тебе на хендл смотреть - непонятно. работай с указателями
> на объекты. в событии OnClientConnect тебе передается Socket.
> Создаешь ClientSocket и ссылку на него сохраняешь в Socket.Data.
> в ClientSocket.Socket.Data сохраняешь ссылку на Socket.
> таким образом, при любом событии будешь знать куда писать.


Мне уже говорили использовать socket.data. Но без примера как его использовать. А я первый раз решил что-то написать с использованием сокетов. Ну и ни литературы соответствующей нет и инет тормозной чтобы по поисковикам искать инфу. Остается только экспериментировать. Но на это много времени уходит. Единственный нормальный источник информации для меня это этот форум, но с к сожалению те кто что-то знают обычно не разъясняют подробно.
Хотя ладно. Думаю с этим сам разберусь. По крайней мере попытаюсь.

А вот насчет того почему некоторые соединения в serversocket сами исчезают не вызывая при этом соответствующих событий я не могу понять.

Например:
В какой-то момент времени есть несколько активных клиентских сокетов и соответствующее число активных соединений в серверном сокете.
При дисконекте клиентского сокета я дисконектю соответствующее соединение в серверном сокете.
Но после окончания загрузки оказывается что нет активных соединений в серверном сокете, (все данные уже переданы) но еще остались активные клиентские сокеты, которые конечно дисконектятся через некоторое время (до нескольких минут). Но я в это время не могу переходить по ссылкам в браузере, так как начинают возникать ошибки в моем прокси-сервере. Но после того как дождусь что все клиентские сокеты дисконектятся то могу это делать нормально.
И не знаю как отловить когда дисконектятся соединения в серверном сокете, чтобы деактивировать соотв. клиентские сокеты.
OnClientDisconnect - не генерируется!!!.


 
vitalmoya   (2003-08-14 13:04) [6]

У меня те же проблемы. Почему то событие при подсоединении клиента к серверу onWrite происходит всегда, а onRead не всегда.
Я так понимаю что сначала должно идти onRead, здесь мы узнаем
HTTP заголовок, а когда уже onWrite передаем нужные даные. Но
почему то onread происходит не вседа, а если и происходит то иногда ReceiveText пусто. В чем проблема


 
Digitman   (2003-08-14 14:26) [7]


> я первый раз решил что-то написать с использованием сокетов


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

на основе простейшей логики простейшего чата как раз и легче всего осознать условия, механику и последовательность возникновения тех или иных событий. Простейший чат потребует всего один-единственный компонент TServerSocket (серверная сторона) и по одному компоненту TClientSocket - для каждого отдельного клиента. Куда уж проще экспериментировать ! Никаких связок, никаких сложностей ...


 
Digitman   (2003-08-14 14:55) [8]


> vitalmoya


OnWrite() как минимум однократно (и - безусловно) сразу же за событием OnConnect(). Факт возникновения этого события говорит о готовности передатчика гнезда к приему "порции" поточных данных для последующей передачи партнеру по каналу установленной вирт.связи. В последствии OnWrite() возникает при условии, что перед этим был вызван какой-либо send-метод, в ходе исполнения которого буфер передачи гнезда не смог вместить всех затребованных к передаче данных. Скажем, методом SendText() была затребована к передаче строка длиной 10kb, в то время как при данных сетевых условиях буфер размером в 8кб не может "прокачать" через себя в канал связи сразу всю строку, за ограниченное системными и сетевыми условиями время. В этом случае SendText() вернет результат = -1, что ни один байт стр.данных не был поставлен в очередь на передачу и что следует повторить попытку постановки в очередь передачи той же строки тем же методом SendText(), но не ранее чем в обработчике обязательно возникающего позже события OnWrite() (т.е. буфер очереди передачи освободился, можно попытаться повторить запись в него данных, с требуемой позиции)

Событие OnRead() означает, что буфер очереди (!!) приема гнезда не пуст. Вызванный в его обработчике метод ReceiveText() вернет ВСЕ содержимое буфера очереди приема, которое доступно для чтения в этот момент. А там может оказаться все что угодно : и "целый" запрос, и фрагмент запроса, и несколько запросов одновременно. Ибо поток (!!) транслируемых данных, формируемый на стороне передатчика вызовами нескольких send-методов (например, SendText), передается стороне приемника фрагментами заранее неизвестного (!!) размера, по мере возникновения соотв.сетевых условий. "Сборку" фрагментов потока в ожидаемые (по соответствующему протоколу инф.обмена) структуры на стороне приемника как раз и следует выполнять в событии OnRead(), всякий раз при возникновении оного "читая" из гнезда ровно столько данных, сколько требуется для получения очередной ожидаемой целостной структуры. Если после "вычерпывания" фрагмента буфер гнезда остается еще не пуст, то после завершения обработки OnRead() это событие возникнет вновь.


 
vitalmoya   (2003-08-14 18:20) [9]

>Digitman
Спасибо за ликбез.


 
SergP   (2003-08-14 19:20) [10]


>
> OnWrite() как минимум однократно (и - безусловно) сразу
> же за событием OnConnect(). Факт возникновения этого события
> говорит о готовности передатчика гнезда к приему "порции"
> поточных данных для последующей передачи партнеру по каналу
> установленной вирт.связи. В последствии OnWrite() возникает
> при условии, что перед этим был вызван какой-либо send-метод,
> в ходе исполнения которого буфер передачи гнезда не смог
> вместить всех затребованных к передаче данных. Скажем, методом
> SendText() была затребована к передаче строка длиной 10kb,
> в то время как при данных сетевых условиях буфер размером
> в 8кб не может "прокачать" через себя в канал связи сразу
> всю строку, за ограниченное системными и сетевыми условиями
> время. В этом случае SendText() вернет результат = -1, что
> ни один байт стр.данных не был поставлен в очередь на передачу
> и что следует повторить попытку постановки в очередь передачи
> той же строки тем же методом SendText(), но не ранее чем
> в обработчике обязательно возникающего позже события OnWrite()
> (т.е. буфер очереди передачи освободился, можно попытаться
> повторить запись в него данных, с требуемой позиции)


А можно ли каким-то образом узнать можно ли в ClientSocket передавать данные с помощью SendText() не вызывая SendText(), т.е. сначала узнать, а потом если можно то уже пытаться передавать?


 
Digitman   (2003-08-15 09:19) [11]

нет, нельзя.
а зачем это нужно ?
вызвал SendText(), получил отказ = -1 (буфер занят) - жди события и повторяй ту же логику !


 
SergP   (2003-08-15 13:28) [12]

Дело в том что есть такая проблема: Данные от TServerSocket я получаю в его эвенте OnClientRead. Перед этим по событию OnClientConnect создаю и активирую TClientSocket. при срабатывании OnClientRead я могу забирать данные, но передавать их в TClientSocket я могу только после то он сконектится и сгенерирует OnWrite. Если я буду в этом событии передавать данные Но этот эвент срабатывает только один раз. Т.е. в таком случае я передаю данные в Tclientsocket, но если браузер снова посылает запрос по этому же соединению, то теперь я должен его передавать в TClientSocket не в его событии OnWrite.
Это несколько усложняет программу так как приходидится создавать массив для хранения данных полученых от TServerSocket но еще не отправленых в TClientSocket, так как один раз получив данные из Tserversocket Я их больше оттуда не получу.

Думал сделать так:
----------------------
Событие OnClientRead TServersocket:
Проверяем можно ли писать в TClientSocket:
Если можно то забираем их c TServersocket и передаем в TClientSocket.
Если нельзя (т.е. TclientSocket еще не сконектился или его буфер переполнен) то ничего не делаем, т.е. данные с Tserversocket не забираем.

Событие OnWrite TClientSocket:
Забираем данные из TServerSocket и передаем в TClientSocket
--------------------


 
Polevi   (2003-08-15 14:13) [13]

>SergP © (15.08.03 13:28) [12]
создавай список данных, в OnRead заполняй его, в OnWrite пытайся передать весь список. Если получил -1 - продолжишь в следующем OnWrite


 
SergP   (2003-08-15 14:48) [14]


> Polevi © (15.08.03 14:13) [13]
> >SergP © (15.08.03 13:28) [12]
> создавай список данных, в OnRead заполняй его, в OnWrite
> пытайся передать весь список. Если получил -1 - продолжишь
> в следующем OnWrite


Пока так и делаю (вернее почти так). Дело в том что (я так понимаю) если я в OnWrite отправляю данные и не получаю -1, то больше OnWrite не будет. следующие данные приходится отправлять в OnClientRead. А это не совсем удобно.


 
Digitman   (2003-08-15 16:31) [15]


> не совсем удобно


потому что некрасиво ты все это организуешь.

задача в теле обработчика OnClientRead() - сформировать новый поток (очередь) передачи либо дописать в хвост существующей очереди то, что следует передать. Как только это сделано (перед выходом из обработчика OnClientRead), следует явно ("вручную") вызвать метод, назначенный событию OnClientWrite().

Задача в теле обработчика OnClientWrite() - получить параметры тек.очереди передачи (например, адрес буфера очереди, размер очереди, смещение от начала). Если очередь непуста, выполнить, например, SendBuf(адрес буфера + смещение , размер еще непереданного хвоста). По результатам SendBuf() скорректировать тек.смещение либо удалить буфер, если достигнут хвост очереди



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

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

Наверх





Память: 0.51 MB
Время: 0.01 c
3-40269
ss300
2003-09-23 08:19
2003.10.13
подключение к ОРАКЛ через Оракл


14-40608
beginner_nostra
2003-09-25 01:36
2003.10.13
Siemens C55 в качестве GPRS модема


14-40666
Knight
2003-09-23 19:02
2003.10.13
Появилось


14-40634
Knight
2003-09-22 11:30
2003.10.13
---|Ветка была без названия|---


14-40587
Дмитри
2003-09-25 10:56
2003.10.13
Что лучше ?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский