Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 5 337

/ вопрос решён /

Здравствуйте, уважаемые эксперты!

Как можно отследить событие на ServerSocket при физической потере связи?

Программа клиент-сервер на компонентах ServerSocket ClientSocket.
Если соединение рвется физически, например, пропала сеть у клиента, то Сервер этого не видит у него все ОК.
Как это можно отследить?

Пробовал отследить по-разному:
Узнаю номер уже несуществующего соединения = i
ServerSocket1.Socket.Connections[i].Connected - выдает True!

Пытался посылать сообщения данному Connections - сперва молчит... типа отослал... потом минут через 5 срабатывает событие onClientError c ошибкой 10053

Как это можно форсировать?
Чтобы я мог онлайн проверить есть ли сейчас физически связь или нет с клиентом?

neon Вопрос решён, но можно продолжить его обсуждение в мини-форуме

Вопрос задал: neon (статус: Посетитель)
Вопрос отправлен: 29 мая 2011, 18:06
Состояние вопроса: решён, ответов: 1.

Ответ #1. Отвечает эксперт: Вадим К

Здравствуйте, neon!
5 минут неответа - это абсолютно нормально. Можно сделать большие выкладки тут, вдаваясь в глубины TCP/IP стека, но поверьте мне на слово - 3-5 минут - это абсолютно нормально и штатно. То есть, если с той стороны клиент отвалился, то в течении 3 минут сервер может ничего не узнать.
В таких случаях применяют готовое решение - KeepAlive пакеты. Они есть штатные, но отсылаются по умолчанию раз в несколько часов:)
Поэтому делаете в своем протоколе специальную команду, к примеру Ping. А клиент, получив ее обязан максимально быстро ответить Pong.
И клиент, и сервер знают, что если ответ не пришел в течении 30 секунд, значит соединение считается утерянным.
Это правильный и надежный метод. Его к примеру применят IRC.

Ответ отправил: Вадим К (статус: Академик)
Время отправки: 29 мая 2011, 20:50
Оценка за ответ: 5

Комментарий к оценке: Хорошо показали методы взаимодействия клиент-сервера при появлении ошибок, например таких как "физическая" потеря соединения.

Мини-форум вопроса

Всего сообщений: 13; последнее сообщение — 30 мая 2011, 21:35; участников в обсуждении: 4.
bugmenot

bugmenot (статус: 3-ий класс), 29 мая 2011, 21:00 [#1]:

Цитата (Вадим К):

раз в несколько часов

t <= 4 минуты
виконання програми розпочинається з того самого мiсця, де призупинилося.

Вадим К

Вадим К (статус: Академик), 29 мая 2011, 21:32 [#2]:

все зависит от кучи настроек.
Галочка "подтверждения прочтения" - вселенское зло.
neon

neon (статус: Посетитель), 29 мая 2011, 22:14 [#3]:

Вадим К
Хорошо прежде, чем отправить сообщение, делаем пинг, потом посылаем.

А остальному списку пользователей шлем каждые минут 10 служебные сообщения, если кто-то не в сети то соединение отвалится и выдаст ошибку. Вот тут проблемка.

У меня все пользователи в таблице БД Postgres забиты.
Добавляю запись в таблицу при подключении юзера и удаляю при отключении.
При нештатной ситуации Соединение отвалилось, теперь мне нужно сделать изменения в таблице.
Придется пробежаться по всем соединениям и занова заполнить таблицу?
или есть способ узнать какое именно соединение отвалилось и тогда бы я удалил только его?
Вадим К

Вадим К (статус: Академик), 30 мая 2011, 00:32 [#4]:

Ну и что же Вы в вопросе не написали об этом? а телепатия моя не в состоянии угадать, что у Вас там проблема с тем, что бы узнать, кто именно отвалился.
К тому же, если бы Вы чуточку, самую малость подумали, то поняли, что решение у Вас под носом.
Посылать перд каждым служебных сообщением пинги не нужно. Да и напрасно. Само служебное сообщение фактически является пингом. Нужно только что бы клиент на него был обязан отвечать.
После любого ответа от пользователя, обновляем для него время последнего ответа в базе. Время от времени просматриваем таблицу. Если там есть клиент, для которого ответы не были получены очень давно - отсылаем ему пинг. При следующем проходе находим клиентов, которые ответ не прислали и удаляем их (отмечаем отключившимися).
А теперь перейдем к интересному, к событию onClientError. Из него можно выудить кое-какую информацию. Там есть параметры, один с них называется Socket (он должен быть вторым). У него есть поля RemoteAddress и RemotePort. Если у Вас на каждом компе строго по одному клиенту, то можно уже идентифицировать клиента. С другой стороны, У TServerSocket есть список клиентских подключений - можно пробежать по ним и найти нужное подключение. А вот как потом сопоставить это подключение с базой - это поможет Ваша единица.

Но тут есть другая проблема - на этом компоненте сложно построить нормальное серверное решение. Хотя некоторые и могут.
Галочка "подтверждения прочтения" - вселенское зло.
neon

neon (статус: Посетитель), 30 мая 2011, 05:58 [#5]:

Вадим К: Но тут есть другая проблема - на этом компоненте сложно построить нормальное серверное решение.

А какие на ваш взгляд и опыт самые стабильные компоненты для организации клиента-сервера?
TcpServer, Indy (IdTCPServer)? или еще что-то?

П.С. Параллельно возникла проблема описанная здесь,
можно попросить вас глянуть
http://expert.delphi.int.ru/question/5302/#msg_25888
Вадим К

Вадим К (статус: Академик), 30 мая 2011, 10:46 [#6]:

Я воздержусь от других комментариев, пока не будет корректно прокомментирована оценка или отозвана.
Галочка "подтверждения прочтения" - вселенское зло.
neon

neon (статус: Посетитель), 30 мая 2011, 13:52 [#7]:

Вадим К: Я воздержусь от других комментариев, пока не будет корректно прокомментирована оценка или отозвана.

Это вы о чем? Что не так???
Вадим К

Вадим К (статус: Академик), 30 мая 2011, 14:11 [#8]:

о этом "Время отправки: вчера, 19:50
Оценка за ответ: 1"
Галочка "подтверждения прочтения" - вселенское зло.
neon

neon (статус: Посетитель), 30 мая 2011, 14:31 [#9]:

Вадим К:
Написано же Комментарий к оценке: работа с сокетами
Или нужно было подробно все расписать?
Короче я не догоняю, где что написать... это так важно?
Вадим К

Вадим К (статус: Академик), 30 мая 2011, 15:01 [#10]:

суть в том, что в той постановке вопроса, в котором Вы хотите решить задачу - она очень плохо решается. И я написал более правильное решение. Которое является классическим решением.

Если клиент с той стороны отвалился, но не сообщил об этом, то в течении нескольких минут об этом сервер обычно не знает. А узнает обычно, когда пытается послать сообщение и не приходит в течении некоторого времени ответ (называемого TimeOut). Если же в сокет ничего не писать и клиент с той стороны отвалился, то узнать об этом нельзя очень долго, если не послать сообщение.
Поэтому читаем вопрос

Цитата:

Как это можно форсировать?
Чтобы я мог онлайн проверить есть ли сейчас физически связь или нет с клиентом?

И мой ответ - послать клиенту ping.
Поэтому я считаю Вашу оценку неверной. И комментарий, который вообще непонятный.
Напрягая телепатию - Вы ищите у сокета какой то метод, который бы моментально бы говорил - есть ли подключение или нет. Отвечу - нет. нет такого.
Галочка "подтверждения прочтения" - вселенское зло.
neon

neon (статус: Посетитель), 30 мая 2011, 15:47 [#11]:

Вадим К:
...Да, я действительно думал, что у сокета есть какой-то метод, который бы моментально бы говорил - есть ли подключение или нет... но вы прекрасно объяснили принципы работы ServerSocket ClientSocket и методы выявления ошибок, чем мне очень помогли! большое спасибо!

... Далее я походу запутался с оценками ответов на вопрос
и изменением репутации в Мини-форуме вопроса, по привычке поставил +1 как в форуме c кратким комментом извините :-[
Как-то не очень хорошо получилось

Как мне сейчас изменить комментарий?
Вадим К

Вадим К (статус: Академик), 30 мая 2011, 16:34 [#12]:

обратится к администратору.
Галочка "подтверждения прочтения" - вселенское зло.
Ерёмин А.А.

Ерёмин А.А. (статус: *Администратор), 30 мая 2011, 21:35 [#13]:

По просьба автора вопроса оценка -1 удалена. Поаккуратнее в следующий раз.

31 мая 2011, 06:53: Статус вопроса изменён на решённый (изменил автор вопроса — neon)

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 4 декабря 2022, 13:59
Выполнено за 0.02 сек.
Рейтинг@Mail.ru