В случае построения системы из необслуживаемых сервера и клиентов необходимо обеспечить надёжность соединения между ними, добавив самовосстановление/переподключение после потери связи. Нужно отслеживать эту ситуацию и на сервере, и на клиенте.
В качестве модельного проекта я вновь использую систему из статьи «JSON-транспорт между микроконтроллером и сервером». Подробное описание процесса установки TCP-соединения — в статье «Установка TCP-соединения в стеке lwIP», обязательно прочитайте её, а то будет непонятно.
Клиент
Во-первых, назначим функцию-обработчик ошибок:
tcp_err(TCPSockJSON, json_client_err);
Эта функция (json_client_err) будет пытаться снова поднять соединение с сервером:
static void json_client_err(void *arg, err_t err)
{
LOG("JSON transport error\n");
json_status = 0;
setTimeout(InitJSON, 1000);
}
Функция setTimeout ставит в расписание выполнение функции InitJSON через 1000 миллисекунд. Эти асинхронные действия назначаются так:
struct struct_async_task {
uint32_t timeout;
void (* async)(void);
} async_task;
void setTimeout(void (* async)(void), uint32_t delay)
{
async_task.timeout = MS_TIMER + delay;
async_task.async = async;
}
И обрабатываются вызовом функции MakeAsyncTasks() по прерываниям от системного таймера. Переменная MS_TIMER инкрементируется каждую миллисекунду и служит таймштампом. В этой реализации пока можно назначить только одно асинхронное задание.
void MakeAsyncTasks()
{
if(async_task.timeout > MS_TIMER) {
async_task.async();
async_task.timeout = 0;
}
}
Также нам потребуется глобальный флаг, говорящий о наличии связи с сервером. При успешном подключении мы устанавливаем его, а после ошибки сбрасываем.
int json_status = 0;
static err_t json_connected(void *arg, struct tcp_pcb *pcb, err_t err)
{
json_status = 1;
return err;
}
Все функции отправки данных теперь нужно обвязать условием if(json_status) { … }.
Теперь при потере связи клиент будет уходить в начальное состояние и ежесекундно пытаться вновь связаться с сервером вплоть до успеха.
Сервер
По сути, в коде сервера на node.js нужно лишь добавить обработчик ошибки, который может к примеру просто сообщать об ошибке в лог.
socket.on('error', function(error) {
console.log('Error:', error);
});
Больше действий не требуется.
Тест
Для проверки можно выключить клиент и включить снова. Сервер напишет в логе об ошибке, и снова примет подключение клиента.
Теперь выключим сервер, заранее открыв лог клиента (у меня он сделан по telnet). При падении связи клиент напишет ошибку, и спустя секунду попробует подключиться снова. Если не запускать сервер — клиент так и будет раз в секунду пытаться подключиться.
Как только сервер будет запущен вновь, клиент успешно к нему подключится.
Свежие комментарии