#c# #php #mysql #.net
Вопрос:
Как я могу создать сценарий на стороне сервера для проверки клиентов на mysql и Windows form, чтобы узнать, вошли ли они в систему? Например, пропингуйте клиента, и он должен что-то сделать в ответ, чтобы убедиться, что он все еще в Сети.
Комментарии:
1. Соединения Mysql являются постоянными, поэтому, если клиент перейдет в автономный режим, он прекратит соединение. Вы также можете установить тайм-ауты для бездействующих подключений.
2. Извините, что я должен был уточнить больше. Поэтому на экране входа в систему моего приложения Windows я вхожу в пользовательскую таблицу в базе данных mysql и просто записываю ее с помощью записи под названием «islogged», и когда приложение завершает работу, я обновляю эту таблицу islogged = «НЕТ». Однако, если пользователь, например, теряет подключение к Интернету перед выходом из приложения, эта запись повторяется в islogged = «НЕТ», а затем они не могут снова войти в систему на более позднем этапе, потому что я проверяю, вошел ли пользователь в систему, прежде чем разрешить им войти
3. Если у вас есть двухуровневое приложение (клиент-база данных), то вы мало что можете с этим поделать, не переписывая существенно своих клиентов. Если у вас есть трехуровневое приложение (клиент-сервер приложений — база данных), вы можете включить эту функцию на уровне сервера приложений.
Ответ №1:
Вы не можете напрямую пинговать клиента с сервера, но есть несколько вариантов.
О тайм-аутах
Я думаю, что в любом случае вам нужно использовать тайм-аут на стороне сервера (wait_timeout), этот тайм-аут может быть установлен на уровне сервера или при подключении с клиента, например:
SET SESSION wait_timeout = 60
Это необходимо, потому что клиент может внезапно исчезнуть, даже не закрыв tcp-соединение, и явный тайм-аут поможет mysql закрыть соединение и освободить ресурсы после нескольких секунд ожидания бездействия клиента. Согласно руководству mysql, тайм-аут по умолчанию довольно велик: 28800 секунд.
Есть один недостаток. Если во время нормальной работы ваш клиент может быть неактивен более секунды wait_timeout, то либо клиент должен знать, как работать с закрытым соединением (повторно подключиться, когда база данных сообщит, что оно отключено), либо он должен отправлять запросы «ping» (например select 1
) по крайней мере каждые wait_timeout - 1
секунды.
Использование функции get_lock()
Начиная с mysql 5.7(а также в mariadb с 10.0.2) вы можете использовать несколько блокировок на уровне пользователя.
Блокировка, полученная с помощью GET_LOCK (), освобождается явно путем выполнения RELEASE_LOCK() или неявно при завершении сеанса (обычно или ненормально). Блокировки, полученные с помощью GET_LOCK (), не снимаются при фиксации или откате транзакций.
Таким образом, идея состоит в том, чтобы выполнить запрос get_lock при подключении клиента, например:
SELECT GET_LOCK('logged_in_{CLIENT_ID}', timeout)
Вы можете установить время ожидания равным 0 и сразу сообщить, что клиент не может войти в систему, или вы можете подождать (заблокировать) не более секунды wait_timeout, чтобы убедиться, что действительно есть другой клиент, удерживающий блокировку.
Эта блокировка будет автоматически снята сервером при отключении клиента или после отключения ожидания бездействия. Если блокировка свободна, get_lock() вернется 1
в противном случае (после секунд ожидания) вернется 0
Использование идентификатора процесса
Если вы не хотите использовать блокировки, можно использовать PID процесса.
Когда клиент подключается, вместо записи islogged = 'YES'
вы можете использовать в качестве значения текущий идентификатор подключения (). Перед входом в систему вы можете проверить, что для текущего клиента нет активного процесса, подобного этому
SELECT islogged FROM logged
INNER JOIN information_schema.processlist ON
processlist.id = logged.islogged
WHERE
client_id = ...
И если приведенный выше запрос ничего не возвращает, вы можете вставить новый pid в зарегистрированную таблицу
REPLACE INTO logged SET islogged = CONNECTION_ID(), client_id = ...
Я бы предпочел использовать get_lock (), потому что он кажется проще, не страдает проблемами параллелизма и позволяет реализовать ожидание.
Не забывайте, что тайм-ауты необходимы, и вы должны иметь дело с повторным подключением или отправлять регулярные сообщения, чтобы избежать неожиданных проблем с «сервер ушел» в клиенте.