Russian Qt Forum

Qt => Работа с сетью => Тема начата: Fregloin от Январь 30, 2013, 19:03



Название: Как определить что сетевой интерфейс "упал"?
Отправлено: 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 - то все работает с точностью до наоборот, состояния сокета приходят, но он не биндится к конкретному интерфейсу (а первой сетевой карте в списке)...
Подскажите куда рыть ...