ПрограммированиеФорумСеть

QTcpSocket и обрыв связи RemoteHostClosedError

#0
18:52, 28 авг 2009

Приветствую всех, вот такая вот ситуация:
при обрыве связи прога незаметно для игрока восстанавливает соединение (по крайней мере пытается), все пакеты которые "идут" на отправку скапливаю в неком буфере,
и в случае успешного соединения отправляю на сервер пакет <reconnect> и после него все те пакеты которые были в буфере. Всё хорошо и нормально работает,
за исключением того что сам момент обрыва соединения моментально словить не получается :( сигнал error (RemoteHostClosedError) приходит через секунды 3-5 после отсоединения кабеля,
соответственно состояние сокета в эти 5секунд установлено на QAbstractSocket::ConnectedState, а пакеты в буфер я накапливаю в любом другом состоянии.. в итоге получается что те пакеты
которые уходят на отправку в этот интервал пропадают бесследно :( экспериментировал с flush() он всегда возвращает true даже когда связь оборвана, с waitForBytesWritten(1000) тоже самое

Может кто сталкивался с такой проблемой, как можно определить с точностью до секунды(желательно меньше) что произошел обрыв сети?
Можно конечно считать пакет отправленным только в том случае если сервер сообщил что принял его, но хотелось бы более точно всё же ловить дисконнект.

Спасибо заранее.

Прошло более 3 лет
#1
17:27, 29 июля 2013

Присоединясь к вопросу, пролопатил пол дня интернет - ответа не нашёл ..
Штудирую документацию QT - результата пока что нет...

#2
13:07, 23 сен 2013

QIODevice::write возвращает количество реально записанных байт.
попробуйте сравнивать количество отправленных с размеров вашего пакета.
если совпадает, значит пакет отправлен, и наоборот.

#3
14:13, 23 сен 2013

События "дисконнект" не существует в принципе (за исключением штатного закрытия TCP соединения). Соответственно, дисконнект сигнализируется когда перестают доходить пакеты или переполняются буфера. Т. е. единственный способ определить дисконнект -- получать подтверждения о получении и при определенных условиях считать соединение разорванным. В TCP протоколе это уже реализовано, но TCP -- это не реалтайм протокол, поэтому событие дисконнекта может задерживаться на минуты. В UDP эту функциональность надо делать самому, но зато будет полный контроль над состоянием сети. Можно будет детектировать разрыв в случае, если не дошло ни одно подтверждение в течение, скажем, 1 секунды. Однако, при этом, лаг сети больше секунды приведет к дисконнекту, надо выбирать баланс.

#4
14:26, 23 сен 2013

Это проблема не Qt. Обрыв может быть на любом из узлов между отправителем и получателем и узнать об этом быстро не получится.
Самый надёжный способ - это, дейсвительно, считать данные переданными только по ответу получателя (именно так работает TCP на своём уровне).

#5
18:20, 23 сен 2013

По умолчанию tcp фиксирует обрыв соединения после 30 секунд неудачных попыток доставить пакет, который вы отослали. Если ничего не посылаете, так и вовсе рискуете не обнаружить обрыв.

#6
22:17, 24 сен 2013

1)я бы организовал дополнительный буфер, который потихоньку заполнял
2) оттуда сливал данные в tcp
3) после получения данных на противоположной стороне
4) отправлял бы обратно фактическое кол-во прочитанных байт
5) освобождал бы мой буфер на это кол-во байт

других вариантов скорее всего нет.
можно поиграться скоростью нотификации разрыва соединения разрыва tcp_keepalive (если QTcpSocket позволяет)

p.s кол-во записанных данных в tcp не означает их реальную доставку на другую сторону, а только значит, что TCP их захавал и при возможности отправит.

#7
1:02, 25 сен 2013

"лучшие собаководы" рекомендуют открывать второе ТСР соединение и слать по нему pulse/heartbeat : )

ПрограммированиеФорумСеть

Тема в архиве.