Название: Как определить что сетевой интерфейс "упал"?
Отправлено: Fregloin от Январь 30, 2013, 19:03
Привет. Есть сетевой клиент который по двум сетевым картам получает данные с двух серверов. Забиндить по разным интерфейсам сокеты удалось (по крайней мере под линуксом) и данные пошли. Но теперь возникла проблема - когда сетефой интерфейс падает (к примеру выдернули шнурок, сегмент лег) то сокет никакого уведомления об этом не получает. Он как бы вист на приеме и все (да, сокеты асинхронные через слоты/сигналы). Изза того что сокет не в курсе что читать нечего, программа не переключается на резервный. Если воткнуть назад шнурок, то через несколько секунд чтение продолжается нормально, сигналы коннект/дисконет/ошибка/изменение состояния не приходят.
На ноуте где один сетевой интерфейс таких глюков не наблюдается - выдернул шнурок - пришёл дисконект, воткнул - получил конект.
Название: Re: Как определить что сетевой интерфейс "упал"?
Отправлено: Fregloin от Январь 31, 2013, 11:13
Вот мой код подключения с биндингом void QRawClient::connectToServer() { if(fsocket.state() != QAbstractSocket::UnconnectedState) return;
fmustReconnect = true; if(connectionConfig().interfaceIndex()>=0) { if(!fbindAddress.isNull()) //если биндинг задан, создаем сокет посредством Qt { qDebug("Try bind %i:%s to %s",connectionConfig().interfaceIndex(),qPrintable(connectionConfig().host()),qPrintable(fbindAddress.toString()));
int fd = fsocket.socketDescriptor(); if(fd<0) { fd = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); }
struct sockaddr_in bindAddr;
memset(&bindAddr,0,sizeof(bindAddr));
bindAddr.sin_family = PF_INET; bindAddr.sin_addr.s_addr = htonl(fbindAddress.toIPv4Address());
if(bind(fd,(const struct sockaddr *)&bindAddr,sizeof(bindAddr))!=0) { qDebug("Socket bind to %s failed with reason %s",qPrintable(fbindAddress.toString()),strerror(errno)); shutdown(fd,2); #ifdef Q_WS_WIN32 closesocket(fd); #else close(fd); return; #endif }
struct sockaddr_in connect_addr; memset(&connect_addr,0,sizeof(connect_addr)); connect_addr.sin_family = PF_INET; connect_addr.sin_port = htons(connectionConfig().port());
QHostAddress address(connectionConfig().host()); connect_addr.sin_addr.s_addr = htonl(address.toIPv4Address());
int connect_result = ::connect(fd,(const struct sockaddr *)&connect_addr,sizeof(connect_addr)); qDebug("connect result %i",connect_result); if(connect_result==-1) { qDebug("connect error! %s",strerror(errno)); close(fd); return; } else { bool bind_result = fsocket.setSocketDescriptor(fd,QAbstractSocket::ConnectedState); if(!bind_result) qDebug("binding to native socket failed"); else qDebug("binding to native socket succsseeded"); /* struct timeval tv; tv.tv_sec = 2; tv.tv_usec = 0;
if(setsockopt(fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv))!=0) { qDebug("SO_RCVTIMEO error %s",strerror(errno)); } if(setsockopt(fd,SOL_SOCKET,SO_SNDTIMEO,&tv,sizeof(tv))!=0) { qDebug("SO_SNDTIMEO error %s",strerror(errno)); } */ emit connectedToServer(); }
// fsocket.connectToHost(connectionConfig().host(),connectionConfig().port()); } } }
Он работает, НО не получает уведомления о том, что сеть легла + не все состояния сокета приходят (подключение,поиск имени и т.п.) Если же все закоментировать а подключаться через connectToHost - то все работает с точностью до наоборот, состояния сокета приходят, но он не биндится к конкретному интерфейсу (а первой сетевой карте в списке)... Подскажите куда рыть ...
|