Russian Qt Forum

Qt => Работа с сетью => Тема начата: xaleva от Январь 26, 2010, 11:29



Название: Не происходит событие QAbstractSocket::SocketError
Отправлено: xaleva от Январь 26, 2010, 11:29
Добрый день всем.Никак не могу поймать сигнал QAbstractSocket::SocketError.На одной из веток на этом форуме  http://www.prog.org.ru/topic_11560_0.html (http://www.prog.org.ru/topic_11560_0.html)  нашел описание ситуации,подобной моей.Там все решалось при смене версии на 4.6,у меня это не помогает,вот отрывок кода:

Код:

    connect (_socket,SIGNAL (connected ()),this,SLOT (slotSocketConnected ()));
    connect (_socket,SIGNAL (readyRead ()),this,SLOT (slotSocketReadyRead ()));
    connect (_socket,SIGNAL (disconnected ()),this,SLOT (slotSocketDisconnected ()));
    connect (_socket,SIGNAL(error (QAbstractSocket::SocketError)),this,SLOT (slotSocketError (QAbstractSocket::SocketError)));
    _socket->connectToHost(ip,port,QIODevice::ReadWrite);
    _socket->waitForConnected (1000);

    if (_socket->state() == QAbstractSocket::UnconnectedState)
    {
        ......
    }


В документации есть такой вот момент  http://doc.crossplatform.ru/qt/4.3.2/qabstractsocket.html#error-2 (http://doc.crossplatform.ru/qt/4.3.2/qabstractsocket.html#error-2), попробывал прописать,все равно не помогло.Может кто-нибудь сталкивался с такой проблемой?


Название: Re: Не происходит событие QAbstractSocket::SocketError
Отправлено: BRE от Январь 26, 2010, 11:56
Если хочешь ловить сигналы, то откажись от _socket->waitForConnected (1000);
Код
C++ (Qt)
void ClassName::createConnection( ... )
{
_socket = new QTcpSocket(...);
connect (_socket,SIGNAL (connected ()),this,SLOT (slotSocketConnected ()));
connect (_socket,SIGNAL (readyRead ()),this,SLOT (slotSocketReadyRead ()));
connect (_socket,SIGNAL (disconnected ()),this,SLOT (slotSocketDisconnected ()));
connect (_socket,SIGNAL(error (QAbstractSocket::SocketError)),this,SLOT (slotSocketError (QAbstractSocket::SocketError)));
_socket->connectToHost(ip,port,QIODevice::ReadWrite);
}
 
и по вызовам сигналов будешь определять, что происходит (подключились, пришли данные, произошла ошибка).

И QAbstractSocket::SocketError нужно зарегестрировать в мета-системе.


Название: Re: Не происходит событие QAbstractSocket::SocketError
Отправлено: xaleva от Январь 26, 2010, 12:11
Сделал,теперь работает вроде,но при выдергивании шнура не срабатывает.А вообще должно ли?


Название: Re: Не происходит событие QAbstractSocket::SocketError
Отправлено: Amigo_sa от Январь 26, 2010, 12:14
Сделал,теперь работает вроде,но при выдергивании шнура не срабатывает.А вообще должно ли?
Я слышал, что в qt существует серьезные проблемы с возвращением ошибок связи. Проявляется, например, если во время http или ftp запроса выдернуть сетевой кабель. 1 мой знакомый писал троллям запрос по этому поводу и они обещали поправить к след. релизу.
Как вариант, в своем приложении я тупо делал таймер, который сбрасывается при любом сигнале dataTransferProgress или commandsDone. работает


Название: Re: Не происходит событие QAbstractSocket::SocketError
Отправлено: xaleva от Январь 26, 2010, 13:00
Так,щас заметил что слот срабатывает и при _socket->waitForConnected (1000);  ,когда сокет закрываю.
Однако при вытаскивании шнура события не происходит.А мне как раз нужно ловить это сообщение.Выдергивание шнура - думаю, самая распространенная трабла в моем случае

Вообще кто нить проверял,происходит ли какое нить событие типа дисконнект или один из ерроров когда plugged out ?


Название: Re: Не происходит событие QAbstractSocket::SocketError
Отправлено: BRE от Январь 26, 2010, 13:19
Вообще кто нить проверял,происходит ли какое нить событие типа дисконнект или один из ерроров когда plugged out ?
enum QAbstractSocket::SocketError:
QAbstractSocket::NetworkError   An error occurred with the network (e.g., the network cable was accidentally plugged out).

Но вот отслеживается ли это постоянно - не уверен.
Возможно, это состояние определяется при одном из действий типа connectToHost.


Название: Re: Не происходит событие QAbstractSocket::SocketError
Отправлено: xaleva от Январь 26, 2010, 13:39
Да,я как раз про эту ошибку и говорю.Я ее обрабатываю,но она не происходит при вытаскивании шнура.Кстати,у меня есть тоже такое подозрение,что произойдет при каком нить действии.Сейчас попробую


Название: Re: Не происходит событие QAbstractSocket::SocketError
Отправлено: xaleva от Январь 26, 2010, 14:09
Хм...чтот не     происходит...я уже и  state обрабатываю..все равно при анплагин никакого события не происходит


Название: Re: Не происходит событие QAbstractSocket::SocketError
Отправлено: BRE от Январь 26, 2010, 14:11
Хм...чтот не     происходит...я уже и  state обрабатываю..все равно при анплагин никакого события не происходит
Возможно, на некоторых платформах это работает, а на некоторых нет.
Попробуй погуглить на эту тему и воспользоваться сервисами предлагаемыми конкретной ОС.


Название: Re: Не происходит событие QAbstractSocket::SocketError
Отправлено: Amigo_sa от Январь 26, 2010, 14:29
Вообще кто нить проверял,происходит ли какое нить событие типа дисконнект или один из ерроров когда plugged out ?

Проверял для ftp=соединений. не происходит


Название: Re: Не происходит событие QAbstractSocket::SocketError
Отправлено: xaleva от Январь 26, 2010, 14:35
Да,телнетом тоже пока чтот не начнешь посылать,не почувствует.Складывается ощущение,что зависит все таки от ос..в данный момент сижу на слакваре


Название: Re: Не происходит событие QAbstractSocket::SocketError
Отправлено: xaleva от Январь 26, 2010, 15:48
Да,после проверки телнетом заметил что при выдергивании кабеля он не переходит в вайт...вообщем после недолгих изысканий нашел изначальные настройки в линухе

  # cat /proc/sys/net/ipv4/tcp_keepalive_time
  7200

  # cat /proc/sys/net/ipv4/tcp_keepalive_intvl
  75

  # cat /proc/sys/net/ipv4/tcp_keepalive_probes
  9
т.е 7200 сек кеепелайва)вощем проблема решена,всем спасибо :)


Название: Re: Не происходит событие QAbstractSocket::SocketError
Отправлено: xaleva от Январь 27, 2010, 10:41
Для тех,кто наткнется на подобную траблу,замечу ,что проблема так просто не решается.Дело в том,что

Цитировать
net.ipv4.tcp_keepalive_time = 7200
Переменная определяет как часто следует проверять соединение, если оно
давно не используется. Значение переменной имеет смысл только для тех
сокетов, которые были созданы с флагом SO_KEEPALIVE.

После недолгих поисков находим способ установить SO_KEEPALIVE для моего сокета,а так же программно установить интервал tcp_keepalive_time
Код:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>

....
// эти строки надо написать после того,как сокет перейдет в состояние конектед,потому как до этого setsockopt ругается на плохой дескриптор,что можно понять.
    int optval;
    socklen_t optlen = sizeof(optval);
    optval = 1;
    setsockopt(_socket->socketDescriptor(), SOL_SOCKET, TCP_KEEPIDLE, &optval, optlen);  // Это строкой я устанавливаю интервал tcp_keepalive_time  на 1 сек
    setsockopt(_socket->socketDescriptor(), SOL_SOCKET, SO_KEEPALIVE, &optval, optlen);  //  этой строкой врубаю SO_KEEPALIVE

Вот здесь можно найти подробное описание функции setsockopt и ее свойств http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.commtechref/doc/commtrf2/setsockopt.htm (http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.commtechref/doc/commtrf2/setsockopt.htm)


Название: Re: Не происходит событие QAbstractSocket::SocketError
Отправлено: SABROG от Январь 27, 2010, 12:08
Проблема давно решена уже. Зачем придумывать велосипед? Большинство протоколов реализуют команды типа PING/PONG.


Название: Re: Не происходит событие QAbstractSocket::SocketError
Отправлено: xaleva от Январь 27, 2010, 12:16
Можно по подробнее?


Название: Re: Не происходит событие QAbstractSocket::SocketError
Отправлено: SABROG от Январь 27, 2010, 12:21
Можно по подробнее?

Реализуешь свой протокол общения с клиентом, например на основе опкодов. Заводишь какой-нибудь enum где выделаешь цифру под опкоды PING и PONG. Сервак шлет команду PING клиентам, если ответ PONG долго не приходит - клиент насильно отрубается.

На стороне клиента если команда PING долго не приходит или вообще нет никаких команд - отрубаемся. Таким образом, если выдернуть сетевой шнур, то таймер проверит время последней команды пришедшей с сервера и если оно больше определенного времени - сокет грохается.


Название: Re: Не происходит событие QAbstractSocket::SocketError
Отправлено: xaleva от Январь 27, 2010, 12:57
 :)
спасибо,примерно так себе это и представлял.Только получается,что придумываете велосипед вы,предлагая создать собственный протокол,когда есть вариант воспользоваться парой функций.Хотя надо признать,я тоже думал в эту сторону,и если бы не нашел решения,сделал бы тоже самое.


Название: Re: Не происходит событие QAbstractSocket::SocketError
Отправлено: SABROG от Январь 27, 2010, 13:47
Я не знаю какую сетевую программу вы пишете, с готовым протоколом или собственным. Просто говорю как делают в тех же mmorpg играх.