Определение доступности UDP сервера
Занимаюсь разработкой многопользовательского редактора топологии ЛВС, использующего протокол UDP и асинхронные сокеты.
Один из компьютеров выступает в роли сервера, к которому подключаются клиенты.
В случае падения сервера, один из клиентов должен принять эстафету от сервера и стать сервером.
Проблема в том как определить сам факт того, что сервер упал (например из-за падения сети).
Каким образом можно определить, доступен сервер или нет?
sendto никогда не возвращает SOCKET_ERROR, даже если сообщение посылается на совершенно левый адрес.
В случае падения сервера, один из клиентов должен принять эстафету от сервера и стать сервером.
Проблема в том как определить сам факт того, что сервер упал (например из-за падения сети).
ваша задача напоминает мне механизм определения Master Browser в сетях Microsoft.
используйте переодические броадкасты с клиентов, для определения текущего главного сервера. по алгоритму:
1. всем чмоке, а кто сейчас сервер?
2. получен ответ - заканчиваем работу алгоритма, сервер известен.
3. ответа нет - инициируем выборы нового сервера
4. выборы по определенному алгоритму прошли - определен новый главный сервер - через некоторое время переходим к пункту 1.
ну и тут следует учесть ньюансы. например - инициализации выборов сервера, при обнаружении падения сервера, при попытке с ним пообщаться, а не во время броадкаста.
Изначально предполагал следующее решение данной проблемы.
Сервер постоянно отсылает широковещательные сообщения со своим именем.
Каждому клиенту при подключении к серверу выдается целочисленный идентификатор.
На каждое сообщение клиента сервер должен прислать сообщение подтверждение, если подтверждение не пришло - сервер упал. Клиент засыпает на количество секунд равное идентификатор_клиента * некая_константа, после пробуждения проверяет передает ли кто-нибудь широковещательные сообщения с именем только-что упавшего сервера. Если да - подключаемся, нет - запускаемся в режиме сервера, и начинаем вещать имя упавшего сервера.
Но вот с подтверждениями проблема.
Пользователь на клиентской машине передвинул элемент, мы отсылаем сообщение о произошедшем серверу, и должны принять подтверждение. Проблема в том, что к этому времени на сокете может быть n-ое количество сообщений от сервера, и как мне оттуда вытащить подтверждение?
Ты уверен что этот вариант сработает?
Но тогда вопрос, как и буду различать на сервере с какого адреса пришли датаграммы?
#include <WinSock2.h>
#include <winbase.h>
int main()
{
WSAData wsd;
if(WSAStartup(MAKEWORD(2, 2), &wsd) == SOCKET_ERROR){
std::cout << "WSAStartup call failed. WSAError" << WSAGetLastError() << std::endl;
return 0;
}
SOCKET s;
if((s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET){
std::cout << "socket call failed. WSAError" << WSAGetLastError() << std::endl;
return 0;
}
sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(35000);
server.sin_addr.s_addr = inet_addr("100.100.100.1");
if(connect(s, (sockaddr*)&server, sizeof(server)) == SOCKET_ERROR){
std::cout << "connect call failed. WSAError" << WSAGetLastError() << std::endl;
return 0;
}
char data[] = "Test";
while(send(s, data, strlen(data) + 1, 0) != SOCKET_ERROR)
std::cout << "send call successful" << std::endl;
return 0;
};
Опять же никаких ошибок:(.