Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Вопрос по клиентской части [D7, WinXP]


Dmitry_177 ©   (2007-04-22 20:13:00) 

Есть клиент-серверное приложение. Клиент отправляет на сервер определенные данные, сервер обрабатывает их и присылает клиенту ответ. Но клиент т.к. не постоянно отправляет на сервер данные, и чтобы сервер не работал в холостую с данным клиентом, если связь с ним была утеряна, сервер в минуты простоя(когда от клиента ничего не приходит), каждые 5 мин. отправляет клиенту запрос, чтобы клиент немедленно ответил на него, т.е. это для проверки связи.. так вот.. когда клиент отправляет и принимает данные, то код по нажатию той же кнопки выглядит примерно так:

send(Sock...)
recv(Sock...)
send(Sock...)
recv(Sock...)
...

но т.к. еще и раз в 5 мин приходит пакет от сервера на подтверждение связи, я при старте клиента создал поток на постоянный прием этого пакета по тому же сокету который используется при обмене информацией, если он пришел то немедленно отчает на него..

function ThreadSocket(Param: Pointer): DWORD; stdcall;
var
 iSend: Integer;
 iRecv: Integer;
 RecvSize: Integer;
begin
 while true do
   begin
     RecvSize := recv(Sock,  iRecv, SizeOf(iRecv), 0);
     if RecvSize > 0 then
       if iRecv = CHECK then
         begin
           iSend := CHECK_OK;
           send(Sock, iSend, SizeOf(iSend), 0);
         end;
   end;
end;

Но проблема в том что этот поток работает паралельно.. и когда данные посредством recv должны придти в определенную функцию, они бывают приходят в тот поток.. и получается так что программа зависает, т.к. функция не получила ответ от сервера и продолжает его ждать... Как можно с этим бороться? Помогите пожалуйста..


SpellCaster   (2007-04-23 15:18:00) [1]

> а таймер на сервере реализовать с помощью select-а, естественно
> потом recv и все это в цикле..?

Массив, состоящий из дескрипторов клиентских сокетов и кол-ва секунд, оставшихся до закрытия каждого из них. Один таймер, который в цикле уменьшает эти значения и если они становятся <0, убивающий соотв. сокет. ибо же можно хранить время закрытия сокета : тогда не надо будет ничего уменьшать.


Сергей М.   (2007-04-23 14:44:00) [2]


> таймер на сервере реализовать с помощью select-а, естественно
> потом recv и все это в цикле..?


Как удобней, так и реализуй.


Dmitry_177   (2007-04-23 14:34:00) [3]

а таймер на сервере реализовать с помощью select-а, естественно потом recv и все это в цикле..?


Сергей М.   (2007-04-23 11:39:00) [4]


> если в течение 5 мин. от клиента ничего не приходило, то
> сервер делает таКую проверку


Да нашута оно нужно серверу-то ?!

Сам клиентдолжен беспокоится о том, чтобы регулярно подавать "признаки жизни" !
Т.е. инициатором KeepAlive-обмена должен выступать клиент, а не сервер. А у тебя им почему-то является сервер).. Что, твоему серверу больше нечем заняться, как только будить "задремавших" клиентов ?


Dmitry_177   (2007-04-23 11:25:00) [5]

клиент соединен с сервером постоянно.. "я жив" это только для проверки связи.. если в течение 5 мин. от клиента ничего не приходило, то сервер делает таКую проверку, если все ок то серве
опять ждет 5 мин. до следующей проверки.. вот как мне в клиенте ловить этот пакет "я жив"?


Сергей М.   (2007-04-23 10:56:00) [6]


> Dmitry_177


Логика, которую ты пытаешься реализовать, вовсе не требует каких-то сложных ухищрений.

1. Сервер, акцептировав клиентское соединение, тут же инициирует 5-тиминутный таймер.

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

3. Иначе, получив до истечения 5-ти минут от любой запрос, сервер реинициирует 5-минутный таймер, после чего анализирует содержимое запроса.
Если запрос вида "я жив", сервер ничего не делает, иначе обрабатывает запрос и возвращает клиенту результат обработки.


Dmitry_177   (2007-04-23 10:37:00) [7]

А как тогда сделать без дополнительного потока?

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


Dmitry_177   (2007-04-23 10:35:00) [8]

А как тогда сделать без дополнительного потока?

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


Kedge   (2007-04-23 10:20:00) [9]

А, разве, у Сокетов нет события разрыва связи ? (я просто не в курсе)


Сергей М.   (2007-04-23 08:12:00) [10]

Доп.поток тут как телеге пятое колесо.


grisme   (2007-04-23 07:50:00) [11]

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


Наверх

Титульная страница Поиск, карта сайта Написать письмо