Приветствую всех, вот такая вот ситуация:
при обрыве связи прога незаметно для игрока восстанавливает соединение (по крайней мере пытается), все пакеты которые "идут" на отправку скапливаю в неком буфере,
и в случае успешного соединения отправляю на сервер пакет <reconnect> и после него все те пакеты которые были в буфере. Всё хорошо и нормально работает,
за исключением того что сам момент обрыва соединения моментально словить не получается :( сигнал error (RemoteHostClosedError) приходит через секунды 3-5 после отсоединения кабеля,
соответственно состояние сокета в эти 5секунд установлено на QAbstractSocket::ConnectedState, а пакеты в буфер я накапливаю в любом другом состоянии.. в итоге получается что те пакеты
которые уходят на отправку в этот интервал пропадают бесследно :( экспериментировал с flush() он всегда возвращает true даже когда связь оборвана, с waitForBytesWritten(1000) тоже самое
Может кто сталкивался с такой проблемой, как можно определить с точностью до секунды(желательно меньше) что произошел обрыв сети?
Можно конечно считать пакет отправленным только в том случае если сервер сообщил что принял его, но хотелось бы более точно всё же ловить дисконнект.
Спасибо заранее.
Присоединясь к вопросу, пролопатил пол дня интернет - ответа не нашёл ..
Штудирую документацию QT - результата пока что нет...
QIODevice::write возвращает количество реально записанных байт.
попробуйте сравнивать количество отправленных с размеров вашего пакета.
если совпадает, значит пакет отправлен, и наоборот.
События "дисконнект" не существует в принципе (за исключением штатного закрытия TCP соединения). Соответственно, дисконнект сигнализируется когда перестают доходить пакеты или переполняются буфера. Т. е. единственный способ определить дисконнект -- получать подтверждения о получении и при определенных условиях считать соединение разорванным. В TCP протоколе это уже реализовано, но TCP -- это не реалтайм протокол, поэтому событие дисконнекта может задерживаться на минуты. В UDP эту функциональность надо делать самому, но зато будет полный контроль над состоянием сети. Можно будет детектировать разрыв в случае, если не дошло ни одно подтверждение в течение, скажем, 1 секунды. Однако, при этом, лаг сети больше секунды приведет к дисконнекту, надо выбирать баланс.
Это проблема не Qt. Обрыв может быть на любом из узлов между отправителем и получателем и узнать об этом быстро не получится.
Самый надёжный способ - это, дейсвительно, считать данные переданными только по ответу получателя (именно так работает TCP на своём уровне).
По умолчанию tcp фиксирует обрыв соединения после 30 секунд неудачных попыток доставить пакет, который вы отослали. Если ничего не посылаете, так и вовсе рискуете не обнаружить обрыв.
1)я бы организовал дополнительный буфер, который потихоньку заполнял
2) оттуда сливал данные в tcp
3) после получения данных на противоположной стороне
4) отправлял бы обратно фактическое кол-во прочитанных байт
5) освобождал бы мой буфер на это кол-во байт
других вариантов скорее всего нет.
можно поиграться скоростью нотификации разрыва соединения разрыва tcp_keepalive (если QTcpSocket позволяет)
p.s кол-во записанных данных в tcp не означает их реальную доставку на другую сторону, а только значит, что TCP их захавал и при возможности отправит.
"лучшие собаководы" рекомендуют открывать второе ТСР соединение и слать по нему pulse/heartbeat : )
Тема в архиве.