LINUX.ORG.RU

QTcpSocket timeout не реагирует.


0

0

День добрый.
Возникло проблема в qt4.3.3 с timeout tcp соединения.
При разрыве соединения без оповещания, не могу получить сигнал об отключении ( который должен вызываться по timeout). Программа дальше высылает пакеты, не принимая на них подтверждения( ack ).
Хотелось бы как-то отловить ситуацию с неполучением ack в ответ и отключать программу. Я как понимаю это должно происходить автоматически, но не происходит.

bool QAbstractSocket::waitForDisconnected ( int msecs = 30000 )

Waits until the socket has disconnected, up to msecs milliseconds. If the connection has been disconnected, this function returns true; otherwise it returns false. In the case where it returns false, you can call error() to determine the cause of the error.

Я так понимаю эта функция используется? Так что же говорит error()? И на исходник бы хоть одним глазком глянуть.

teferiincub
()
Ответ на: комментарий от teferiincub

Хм. Нет, эта функция не исползуется. Я даже не получаю сообщения об ошибке, программа продолжает работать, не получая никакого сигнала.

Надо чтобы программа отключала соединение, если не получила ответа (ack) на отправленный пакет, т.е. происходил timeout.

TwIsTeD
() автор топика
Ответ на: комментарий от TwIsTeD

я может чего-то недопонимаю, но откуда вы взяли, что если не получен ack, то случилось непоправимое? более того, не на каждый пакет придет ack: это нормальная практика по rfc.

Pi ★★★★★
()
Ответ на: комментарий от Pi

Хм.
Хорошо. Попробую так.
Есть tcp подключение, программа работает И вот после 10-11 часов происходит обрыв соединения без оповещания, т.е. ниодна из сторон не выслает fin или rst, видимо кабель оборвали, роутер где-то взорвали.
Программа дальше высылает пакеты, wireshark показывает 8 tcp retransmission, но пакет так и не доходит, отправляет снова, пакет не доходит, сервер уже отключил меня не оповестив ( видимо решив, что я умер безвозвратно), программа дальше отправляет пакет. И так может тянуться долго.
И вот хотелось бы в данном случае получать disconnect сигнал по какому-то timeout.

TwIsTeD
() автор топика
Ответ на: комментарий от TwIsTeD

а что значит

>программа дальше отправляет пакет.

? оно лочится на write? что возвращает write?

Pi ★★★★★
()
Ответ на: комментарий от TwIsTeD

>И вот хотелось бы в данном случае получать disconnect сигнал по какому-то timeout

сомневаюсь, что так можно

Pi ★★★★★
()

А если просто ловить сигнал disconnected() ???
у меня что то типа:

class CSSocket : public QTcpSocket
{
	Q_OBJECT
public:
	CSSocket();
	virtual ~CSSocket();
	
	void GetReceiveData(QString &cOut);
	void ReceiveWait(bool bWait);
	bool IsReceiveWait();

protected:
	string m_cOutReceive;
	bool m_bIsWait;

private slots:
	void incomingData();
	void OnCls();
};

CSSocket::CSSocket()
{
	m_bIsWait = false;
	connect(this, SIGNAL(readyRead()), this, SLOT(incomingData()));
	connect(this, SIGNAL(disconnected()), this, SLOT(OnCls()));
}

void CSSocket::OnCls()
{
	....
        ....

}


Все работает.




Fastman
()
Ответ на: комментарий от TwIsTeD

Значит че то ты намутил. Только что проверил тупо выдирая сеть из компа сервера - клиенская софтина сразу заорали что связь потеряна.... Код давай..проверим....

Fastman
()
Ответ на: комментарий от Fastman

В коде коннекты слотов и сигналов, как и у тебя в примере.
Какая ОС? запущен ли какой-нибудь демон для отслеживания подключения?

TwIsTeD
() автор топика
Ответ на: комментарий от TwIsTeD

Клиенты под винду,linux,MacOS. Конкретно сейчас с макбукпро выдирал сетевой кабель, клиент сразу словил disconnected(); Никаких больше демонов. При запуске клиента идет авторизация, соединение держится постоянно. На серверном приложении - пулл сокетов. Покажи код..подозреваю что ты не там подписываешься на сигнал.

Fastman
()
Ответ на: комментарий от Fastman

connectionSocket = new QTcpSocket(this);

connect ( connectionSocket, SIGNAL(disconnected()),
this, SLOT(disconnected()));
connect ( connectionSocket, SIGNAL(readyRead()),
this, SLOT(readDataFromSocket()));

connect( connectionSocket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(displayError(QAbstractSocket::SocketError)));

сигнал disconnected() срабатывает при получение fin,rst

TwIsTeD
() автор топика
Ответ на: комментарий от TwIsTeD

connectionSocket = new QTcpSocket(this); 
перепиши: 
QTcpSocket *connectionSocket = new QTcpSocket;

И вот так никогда не пиши.
connect (connectionSocket, SIGNAL(disconnected()),
this, SLOT(disconnected())); 
Зачем называть слот как сигнал ?



 

Fastman
()
Ответ на: комментарий от Fastman

QTcpSocket *connectionSocket;
Указан в private: класса. Или здесь акцентируется внимание на создание без родителя?

А насчёт названия учту.

TwIsTeD
() автор топика
Ответ на: комментарий от TwIsTeD

Очень сложно общаться когда непонятно чего на самом деле нужно. Может у тебя каждое соединение выносится в отдельный поток. Может еще какие нюансы есть.... Хотя бы схематично обрисуй структуру приложения. Тут есть шаманы предсказатели, но они в отпуске :) Чтобы как то решить проблему - ее нужно видеть :)

Fastman
()
Ответ на: комментарий от TwIsTeD

Это пять :) Точнее полный пиз*ц (это я не со зла) :) Так мощно, кратко и емко отразить архитектуру приложения....

Fastman
()
Ответ на: комментарий от Fastman

Я конечно дико извиняюсь, но как-то неочень понимаю.
Я уже писал, что программа реагирует на сигнал disconnected(), который например вызывается при получении fin от сервера. Но я не получаю этого сигнала, если выдернуть кабель.
Чем архитектура программы поможет в данном случае? Ипользуется класс qtcpsocket, не производная своя реализация от него. Нюансов нет. И какие могут быть нюансы в программе с использованием реализованного ( не изменённого ) библиотечного класса, который реагирует на протокольное закрытие соединения, но не реагирует на внешний фактор "давай выдернем кабель?"
Я не знаю, почему у тебя так хорошо с отключением кабеля. Но у меня например запущенный IM клиент ( kopete, sim ) после выдёргивания кабеля из компьютера, на котором запущен клиент не дисконнектится.
Но чёрт с ним, с данным примером.

И в данном случае например wireshark не показывает отправки пакетов от программы.

Но видимо когда связь прерывается где-то там, за первым маршрутизатором и пакеты таки передаются в сеть, я не могу получить так сильно ожидаемого timeout'a, происходит попытка n раз передать высланный пакет, но программа так и не получает сигнала disconnected.

Я не отрицаю тот факт, что тот же kopete в данной ситуации может повёл бы себя так же, но просто если есть решение данной проблемы, то хотелось бы его знать.
Такая проблема может произойти один раз за 10-12 часов и невсегда, остаётся только догадываться, что послужило тому причиной.

Прости, но я действительно не понимаю. Я нихрена не гуру. Рад буду понять. )

TwIsTeD
() автор топика
Ответ на: комментарий от TwIsTeD

Давай тогда не будем гадать... Срисовывай точно тот класс который я тебе привел выше. Дальше привожу куски кода в которых юзаю этот класс.

#include "SSocket.h" class CProjectManager : public QObject { Q_OBJECT

public:

CProjectManager(); ~CProjectManager();

bool Connect(const QString &cIP, qint16 nPort);

CSSocket *m_pSSocket; }

CProjectManager::~CProjectManager() { if(m_pSSocket != NULL) delete m_pSSocket; }

bool CProjectManager::Connect(const QString &cIP, qint16 nPort) { if(m_pSSocket == NULL) m_pSSocket = new CSSocket();

m_pSSocket->connectToHost(cIP, nPort); if(m_pSSocket->waitForConnected(1000)) { return true; } else { delete m_pSSocket; m_pSSocket = NULL; }

return false; }

Вроде ничо не забыл. Сейчас просто нет возможность заглянуть в код. Если не разберешься - давай почту, победим твой баг.

Fastman
()
Ответ на: комментарий от Fastman

Я опять же извиняюсь, в этот раз за наглость.
Но просто на данный момент очень сильно загружен.
И вернусь к этой проблеме только через неделю или две. Хотя очень хотелось бы разобраться сейчас, но..
Может можешь оставить свой контакт? Я напишу позже, когда ко мне явится наконец-то свободное время.

TwIsTeD
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.