Доброго времени суток.
Есть 2 программы, соединяющиеся по юниксовым сокетам. Одно приложение выступает в качестве сервера, другое в качестве клиента. Делаю попытку восстановления соединения на клиенте. То есть если внезапно падает сервер, то раз в сколько-то секунд клиент должен попытаться подключиться.
Теперь код. Создание сокета create():
spoiler::bzero(&_sock, sizeof(_sock)); // _sock имеет тип sockaddr_un
_sock.sun_family = AF_UNIX;
strncpy(_sock.sun_path, socket_name, sizeof(_sock.sun_path) - 1);
_sdSocket = ::socket(AF_UNIX, SOCK_STREAM, 0); // _sdSocket - int
if ( _sdSocket < 0 ) {
showError("Create socket failed. errno: " + std::to_string(errno));
return false;
}
if ( !makeSocketNonBlocking(_sdSocket) ) return false;
if ( !createEpoll() ) return false;
return true;
Функция connect
spoilerint len = strlen(_sock.sun_path) + sizeof(_sock.sun_family);
if ( ::connect(_sdSocket, (struct sockaddr *)&_sock, len) < 0 ) {
showError("Connect socket failed. Errno: " + std::to_string(errno));
return false;
} else {
showInfo("connected to Transceiver");
event.data.fd = _sdSocket;
event.events = EPOLLIN | EPOLLET;
if ( ::epoll_ctl(_sdEpoll, EPOLL_CTL_ADD, _sdSocket, &event) < 0 ) {
if ( _sdEpoll < 0 ) {
showError("epoll_ctl failed");
return false;
}
}
}
return true;
Кусок функции приема пакета, которая отвечает за закрытие сокета
spoilersizeHdr = ::recv(_sdSocket, &buf, sizeof(struct messaging::HugeMessage), 0);
if ( sizeHdr == 0 ) {
::close(_sdSocket);
showInfo("Socket closed");
_connected = false;
}
Т.к. помимо работы с сокетом есть еще задачи для программы, сделал через вечный цикл опрос epoll'a, выглядит так:
spoilerif ( _connected == false) {
//if ( create() ) {
showInfo("Trying connected...");
_connected = connect();
//}
return;
}
int n = epoll_wait(_sdEpoll, arrEvents.data(), countConnect, 0);
if ( n == 0 ) return;
if ( n < 0 ) {
showError("epoll wait");
return;
}
for ( int i{0}; i < n; i++ ) {
if ( arrEvents[i].events & EPOLLERR ||
arrEvents[i].events & EPOLLHUP ||
!(arrEvents[i].events & EPOLLIN) ) {
showError("epoll event error. Errno: " + std::to_string(errno));
if ( _sdSocket == arrEvents[i].data.fd ) {
::close(_sdSocket);
_connected = false;
}
} else {
receiver();
}
}
Вот в последней функции, сначала идет проверка "А есть ли соединение?" и если нет, то пытаемся подключиться. Так вот, если связь была, и сервер упал, то я ловлю это событие, закрываю сокет. На следующей итерации попытка подключиться. И всегда возвращает false. Решил только через костыль (как я считаю), после закрытия сокета, он полностью очищается и по новой вызывается функция ::socket, ::connect и т.д. и вот так работает. Подскажите, пожалуйста, как мне не пересоздавать сокеты, но восстанавливать соединение?