|
Вопрос # 5 337/ вопрос решён / |
|
Здравствуйте, уважаемые эксперты!
Как можно отследить событие на ServerSocket при физической потере связи?
Программа клиент-сервер на компонентах ServerSocket ClientSocket.
Если соединение рвется физически, например, пропала сеть у клиента, то Сервер этого не видит у него все ОК.
Как это можно отследить?
Пробовал отследить по-разному:
Узнаю номер уже несуществующего соединения = i
ServerSocket1.Socket.Connections[i].Connected - выдает True!
Пытался посылать сообщения данному Connections - сперва молчит... типа отослал... потом минут через 5 срабатывает событие onClientError c ошибкой 10053
Как это можно форсировать?
Чтобы я мог онлайн проверить есть ли сейчас физически связь или нет с клиентом?
|
Вопрос задал: 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 (статус: 3-ий класс), 29 мая 2011, 21:00 [#1]:
Цитата (Вадим К):
раз в несколько часов
t <= 4 минуты
виконання програми розпочинається з того самого мiсця, де призупинилося.
|
|
Вадим К (статус: Академик), 29 мая 2011, 21:32 [#2]:
все зависит от кучи настроек.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
neon (статус: Посетитель), 29 мая 2011, 22:14 [#3]:
Вадим К
Хорошо прежде, чем отправить сообщение, делаем пинг, потом посылаем.
А остальному списку пользователей шлем каждые минут 10 служебные сообщения, если кто-то не в сети то соединение отвалится и выдаст ошибку. Вот тут проблемка.
У меня все пользователи в таблице БД Postgres забиты.
Добавляю запись в таблицу при подключении юзера и удаляю при отключении.
При нештатной ситуации Соединение отвалилось, теперь мне нужно сделать изменения в таблице.
Придется пробежаться по всем соединениям и занова заполнить таблицу?
или есть способ узнать какое именно соединение отвалилось и тогда бы я удалил только его?
|
|
Вадим К (статус: Академик), 30 мая 2011, 00:32 [#4]:
Ну и что же Вы в вопросе не написали об этом? а телепатия моя не в состоянии угадать, что у Вас там проблема с тем, что бы узнать, кто именно отвалился.
К тому же, если бы Вы чуточку, самую малость подумали, то поняли, что решение у Вас под носом.
Посылать перд каждым служебных сообщением пинги не нужно. Да и напрасно. Само служебное сообщение фактически является пингом. Нужно только что бы клиент на него был обязан отвечать.
После любого ответа от пользователя, обновляем для него время последнего ответа в базе. Время от времени просматриваем таблицу. Если там есть клиент, для которого ответы не были получены очень давно - отсылаем ему пинг. При следующем проходе находим клиентов, которые ответ не прислали и удаляем их (отмечаем отключившимися).
А теперь перейдем к интересному, к событию onClientError. Из него можно выудить кое-какую информацию. Там есть параметры, один с них называется Socket (он должен быть вторым). У него есть поля RemoteAddress и RemotePort. Если у Вас на каждом компе строго по одному клиенту, то можно уже идентифицировать клиента. С другой стороны, У TServerSocket есть список клиентских подключений - можно пробежать по ним и найти нужное подключение. А вот как потом сопоставить это подключение с базой - это поможет Ваша единица.
Но тут есть другая проблема - на этом компоненте сложно построить нормальное серверное решение. Хотя некоторые и могут.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
neon (статус: Посетитель), 30 мая 2011, 05:58 [#5]:
Вадим К: Но тут есть другая проблема - на этом компоненте сложно построить нормальное серверное решение.
А какие на ваш взгляд и опыт самые стабильные компоненты для организации клиента-сервера?
TcpServer, Indy (IdTCPServer)? или еще что-то?
П.С. Параллельно возникла проблема описанная здесь,
можно попросить вас глянуть
https://expert.delphi-int.ru/question/5302/#msg_25888
|
|
Вадим К (статус: Академик), 30 мая 2011, 10:46 [#6]:
Я воздержусь от других комментариев, пока не будет корректно прокомментирована оценка или отозвана.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
neon (статус: Посетитель), 30 мая 2011, 13:52 [#7]:
Вадим К: Я воздержусь от других комментариев, пока не будет корректно прокомментирована оценка или отозвана.
Это вы о чем? Что не так???
|
|
Вадим К (статус: Академик), 30 мая 2011, 14:11 [#8]:
о этом "Время отправки: вчера, 19:50
Оценка за ответ: 1"
Галочка "подтверждения прочтения" - вселенское зло.
|
|
neon (статус: Посетитель), 30 мая 2011, 14:31 [#9]:
Вадим К:
Написано же Комментарий к оценке: работа с сокетами
Или нужно было подробно все расписать?
Короче я не догоняю, где что написать... это так важно?
|
|
Вадим К (статус: Академик), 30 мая 2011, 15:01 [#10]:
суть в том, что в той постановке вопроса, в котором Вы хотите решить задачу - она очень плохо решается. И я написал более правильное решение. Которое является классическим решением.
Если клиент с той стороны отвалился, но не сообщил об этом, то в течении нескольких минут об этом сервер обычно не знает. А узнает обычно, когда пытается послать сообщение и не приходит в течении некоторого времени ответ (называемого TimeOut). Если же в сокет ничего не писать и клиент с той стороны отвалился, то узнать об этом нельзя очень долго, если не послать сообщение.
Поэтому читаем вопрос
Цитата:
Как это можно форсировать?
Чтобы я мог онлайн проверить есть ли сейчас физически связь или нет с клиентом?
И мой ответ - послать клиенту ping.
Поэтому я считаю Вашу оценку неверной. И комментарий, который вообще непонятный.
Напрягая телепатию - Вы ищите у сокета какой то метод, который бы моментально бы говорил - есть ли подключение или нет. Отвечу - нет. нет такого.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
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)
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|